TemperatureSerialDevice.cs 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309
  1. using Aitex.Core.RT.Event;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.OperationCenter;
  4. using Aitex.Core.RT.Routine;
  5. using Aitex.Core.RT.SCCore;
  6. using Aitex.Core.Util;
  7. using MECF.Framework.Common.Device.TemperatureController;
  8. using System;
  9. using System.Collections.Concurrent;
  10. using System.Collections.Generic;
  11. using System.IO.Ports;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Threading;
  15. using System.Threading.Tasks;
  16. namespace MECF.Framework.Common.Device.ResistivityProbe
  17. {
  18. public enum TemperatureVariableType
  19. {
  20. Decade=0,
  21. Kilo=1,
  22. Buffer=2,
  23. SignedDecade=3,
  24. Alarm=4
  25. }
  26. public class TemperatureSerialDevice
  27. {
  28. #region Delegate
  29. public delegate void UpdateVariableValueChanged(string name,byte address, string variableName, object variableValue);
  30. #endregion
  31. #region 常量
  32. private const byte SOH = 0x01;
  33. private const byte STX = 0x02;
  34. private const byte ETX = 0x03;
  35. private const byte ENQ = 0x05;
  36. private const byte ACK = 0x06;
  37. private const byte CR = 0x0D;
  38. private const byte ADD_FLAG = 0x30;
  39. private const byte MINUS_FLAG = 0x2D;
  40. #endregion
  41. #region 内部变量
  42. /// <summary>
  43. /// 串口
  44. /// </summary>
  45. private SerialPort _serialPort;
  46. /// <summary>
  47. /// 连接状态
  48. /// </summary>
  49. private bool _connected;
  50. /// <summary>
  51. /// 模块名称
  52. /// </summary>
  53. private string _name;
  54. /// <summary>
  55. /// 重连
  56. /// </summary>
  57. private bool _reconnect;
  58. /// <summary>
  59. /// 队列锁
  60. /// </summary>
  61. private object _locker = new object();
  62. /// <summary>
  63. /// 发送队列
  64. /// </summary>
  65. private List<TemperatureSendData> _sendQueueDatas = new List<TemperatureSendData>();
  66. /// <summary>
  67. /// 定时器
  68. /// </summary>
  69. private PeriodicJob _periodJob;
  70. /// <summary>
  71. /// 离线时间
  72. /// </summary>
  73. private DateTime _offlineDateTime;
  74. /// <summary>
  75. /// 接收超时
  76. /// </summary>
  77. private int _receiveTimeOut;
  78. /// <summary>
  79. /// 错误
  80. /// </summary>
  81. private string _errorMsg = "";
  82. /// <summary>
  83. /// 首次连接成功
  84. /// </summary>
  85. private bool _isFirstConnected = false;
  86. #endregion
  87. #region 事件
  88. /// <summary>
  89. /// 变量变更事件
  90. /// </summary>
  91. public event UpdateVariableValueChanged OnUpdateVariableValueChanged;
  92. #endregion
  93. #region 属性
  94. /// <summary>
  95. /// 连接状态
  96. /// </summary>
  97. public bool Connected
  98. {
  99. get { return _connected; }
  100. set
  101. {
  102. _connected = value;
  103. }
  104. }
  105. #endregion
  106. /// <summary>
  107. /// 初始化
  108. /// </summary>
  109. /// <param name="portName"></param>
  110. /// <param name="baudRate"></param>
  111. /// <param name="stopBits"></param>
  112. /// <param name="dataBits"></param>
  113. /// <param name="parity"></param>
  114. public TemperatureSerialDevice(string name, string portName, int baudRate = 9600, StopBits stopBits = StopBits.One, int dataBits = 8, Parity parity = Parity.None,bool reconnect=false,int receiveTimeout=2000)
  115. {
  116. _serialPort = new SerialPort();
  117. _serialPort.BaudRate = baudRate;
  118. _serialPort.StopBits = stopBits;
  119. _serialPort.DataBits = dataBits;
  120. _serialPort.Parity = parity;
  121. _serialPort.PortName = portName;
  122. _serialPort.ReadTimeout = receiveTimeout;
  123. _serialPort.ErrorReceived += SerialPort_ErrorReceived;
  124. _name = name;
  125. _reconnect = reconnect;
  126. _receiveTimeOut = receiveTimeout;
  127. _periodJob = new PeriodicJob(50, OnTimer, $"{_name}_sender", false, true);
  128. }
  129. /// <summary>
  130. /// 初始化
  131. /// </summary>
  132. public void Initialize()
  133. {
  134. _periodJob.Start();
  135. }
  136. /// <summary>
  137. /// 启动
  138. /// </summary>
  139. public void Start()
  140. {
  141. Open();
  142. }
  143. /// <summary>
  144. /// 打开
  145. /// </summary>
  146. private void Open()
  147. {
  148. if (!_connected)
  149. {
  150. try
  151. {
  152. if (!_serialPort.IsOpen)
  153. {
  154. _serialPort.Open();
  155. }
  156. _connected = true;
  157. if (!_isFirstConnected)
  158. {
  159. _isFirstConnected = true;
  160. }
  161. LOG.WriteLog(eEvent.INFO_TEMPERATURE, _name, $"connect {_serialPort.PortName} Success");
  162. }
  163. catch (Exception ex)
  164. {
  165. WriteErrorMsg(ex.Message);
  166. }
  167. }
  168. }
  169. /// <summary>
  170. /// 关闭
  171. /// </summary>
  172. public void Close()
  173. {
  174. try
  175. {
  176. _connected = false;
  177. _serialPort.Close();
  178. }
  179. catch (Exception ex)
  180. {
  181. WriteErrorMsg(ex.Message);
  182. }
  183. }
  184. /// <summary>
  185. /// 出现错误
  186. /// </summary>
  187. /// <param name="sender"></param>
  188. /// <param name="e"></param>
  189. private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
  190. {
  191. LOG.WriteLog(eEvent.ERR_TEMPERATURE, _name, e.EventType.ToString());
  192. }
  193. /// <summary>
  194. /// 定时器
  195. /// </summary>
  196. /// <returns></returns>
  197. private bool OnTimer()
  198. {
  199. if (!_connected)
  200. {
  201. ///离线超过5秒清理发送队列
  202. if(DateTime.Now.Subtract(_offlineDateTime).TotalSeconds>=5&&_sendQueueDatas.Count>0)
  203. {
  204. ClearSendQueue();
  205. }
  206. if (_reconnect)
  207. {
  208. if (_isFirstConnected)
  209. {
  210. Open();
  211. }
  212. }
  213. else
  214. {
  215. _periodJob.Stop();
  216. }
  217. return true;
  218. }
  219. else
  220. {
  221. SendData();
  222. }
  223. return true;
  224. }
  225. /// <summary>
  226. /// 发送数据
  227. /// </summary>
  228. private void SendData()
  229. {
  230. int queueCount = _sendQueueDatas.Count;
  231. if (_sendQueueDatas.Count != 0)
  232. {
  233. lock (_locker)
  234. {
  235. TemperatureSendData data = _sendQueueDatas[0];
  236. _sendQueueDatas.RemoveAt(0);
  237. if (data != null)
  238. {
  239. if (data.Type == 0)//设置
  240. {
  241. WriteInfoMsg(0, $"execute set {data.Type} queue length {queueCount}");
  242. try
  243. {
  244. SettingOperation(data.Id, data.Command, data.Data);
  245. }
  246. catch (Exception ex)
  247. {
  248. WriteErrorMsg(ex.Message);
  249. }
  250. }
  251. else//读取变量
  252. {
  253. WriteInfoMsg(0, $"execute read {data.Type} queue length {queueCount}");
  254. ReadVariableData(data);
  255. }
  256. }
  257. }
  258. }
  259. }
  260. /// <summary>
  261. /// 读取变量
  262. /// </summary>
  263. /// <param name="data"></param>
  264. private void ReadVariableData(TemperatureSendData data)
  265. {
  266. switch(data.VariableType)
  267. {
  268. case TemperatureVariableType.Decade:
  269. if (ReadDecadeParam(data.Id, data.Command, out double decadeValue))
  270. {
  271. _errorMsg = "";
  272. UpdateVariableValue(data,decadeValue);
  273. }
  274. break;
  275. case TemperatureVariableType.Kilo:
  276. if (ReadKiloParam(data.Id, data.Command, out int kiloValue))
  277. {
  278. _errorMsg = "";
  279. UpdateVariableValue(data,kiloValue);
  280. }
  281. break;
  282. case TemperatureVariableType.SignedDecade:
  283. if(ReadSignedDecadeParam(data.Id,data.Command,out double signedDecadeValue))
  284. {
  285. _errorMsg = "";
  286. UpdateVariableValue(data,signedDecadeValue);
  287. }
  288. break;
  289. case TemperatureVariableType.Buffer:
  290. if(ReadBufferParam(data.Id,data.Command,out byte[] buffer,11))
  291. {
  292. _errorMsg = "";
  293. UpdateVariableValue(data,BitConverter.ToString(buffer));
  294. }
  295. break;
  296. default:
  297. break;
  298. }
  299. }
  300. /// <summary>
  301. /// 变量数据
  302. /// </summary>
  303. /// <param name="data"></param>
  304. private void UpdateVariableValue(TemperatureSendData data,object variableValue)
  305. {
  306. data.VariableValue = variableValue;
  307. if(OnUpdateVariableValueChanged!=null)
  308. {
  309. OnUpdateVariableValueChanged(_name,data.Id, data.VariableName, data.VariableValue);
  310. }
  311. }
  312. /// <summary>
  313. /// 清空发送队列
  314. /// </summary>
  315. private void ClearSendQueue()
  316. {
  317. try
  318. {
  319. while (_sendQueueDatas.Count != 0)
  320. {
  321. _sendQueueDatas.Clear();
  322. }
  323. }
  324. catch(Exception ex)
  325. {
  326. WriteErrorMsg(ex.Message,false);
  327. }
  328. }
  329. /// <summary>
  330. /// 插入数据
  331. /// </summary>
  332. /// <param name="data"></param>
  333. private void InsertDataToQueue(TemperatureSendData data)
  334. {
  335. lock (_locker)
  336. {
  337. _sendQueueDatas.Insert(0, data);
  338. }
  339. }
  340. /// 插入数据
  341. /// </summary>
  342. /// <param name="data"></param>
  343. private void AddDataToQueue(TemperatureSendData data)
  344. {
  345. lock (_locker)
  346. {
  347. _sendQueueDatas.Add(data);
  348. }
  349. }
  350. #region Temperature
  351. /// <summary>
  352. /// 插入数据
  353. /// </summary>
  354. /// <param name="data"></param>
  355. private void InsertDatasToQueue(TemperatureSendData data,TemperatureSendData readData)
  356. {
  357. lock(_locker)
  358. {
  359. _sendQueueDatas.Insert(0, readData);
  360. _sendQueueDatas.Insert(0, data);
  361. }
  362. }
  363. /// <summary>
  364. /// 设置温度
  365. /// </summary>
  366. /// <param name="id"></param>
  367. /// <param name="temperature"></param>
  368. /// <returns></returns>
  369. public bool SetTargetTemperature(byte id,double temperature)
  370. {
  371. TemperatureSendData data = new TemperatureSendData();
  372. data.Id = id;
  373. data.Command = 0x31;
  374. data.Data=GetDecadeBytes(temperature);
  375. data.Type = 0;
  376. TemperatureSendData readData = GetReadTargetTemperature(id);
  377. InsertDatasToQueue(data,readData);
  378. return true;
  379. }
  380. /// <summary>
  381. /// 获取读取目标温度指令
  382. /// </summary>
  383. /// <param name="id"></param>
  384. /// <returns></returns>
  385. private TemperatureSendData GetReadTargetTemperature(byte id)
  386. {
  387. TemperatureSendData data = new TemperatureSendData();
  388. data.Id = id;
  389. data.Type = 1;
  390. data.Command = 0x31;
  391. data.VariableName = "TargetTemperature";
  392. data.VariableType = TemperatureVariableType.Decade;
  393. return data;
  394. }
  395. /// <summary>
  396. /// 读取温度
  397. /// </summary>
  398. /// <param name="id"></param>
  399. /// <param name="temperature"></param>
  400. /// <returns></returns>
  401. public void ReadTargetTemperature(byte id)
  402. {
  403. TemperatureSendData data=GetReadTargetTemperature(id);
  404. AddDataToQueue(data);
  405. }
  406. /// <summary>
  407. /// 读取Heat Exchanger温度
  408. /// </summary>
  409. /// <param name="id"></param>
  410. /// <param name="temperature"></param>
  411. /// <returns></returns>
  412. public void ReadHeatExchangerInternelSensorTemperature(byte id)
  413. {
  414. TemperatureSendData data = new TemperatureSendData();
  415. data.Id = id;
  416. data.Type = 1;
  417. data.Command = 0x32;
  418. data.VariableName = "HeatExchangerTemperature";
  419. data.VariableType = TemperatureVariableType.Decade;
  420. AddDataToQueue(data);
  421. }
  422. /// <summary>
  423. /// 读取Reservior温度
  424. /// </summary>
  425. /// <param name="id"></param>
  426. /// <param name="temperature"></param>
  427. /// <returns></returns>
  428. public void ReadReserviorExtendSensorTemperature(byte id)
  429. {
  430. TemperatureSendData data = new TemperatureSendData();
  431. data.Id = id;
  432. data.Type = 1;
  433. data.Command = 0x33;
  434. data.VariableName = "ReserviorTemperature";
  435. data.VariableType = TemperatureVariableType.Decade;
  436. AddDataToQueue(data);
  437. }
  438. #endregion
  439. #region Alarm
  440. /// <summary>
  441. /// 读取Alarm状态
  442. /// </summary>
  443. /// <param name="id"></param>
  444. /// <param name="status"></param>
  445. /// <returns></returns>
  446. public void ReadAlarmStatus(byte id)
  447. {
  448. TemperatureSendData data = new TemperatureSendData();
  449. data.Id = id;
  450. data.Type = 1;
  451. data.VariableName = "Alarm";
  452. data.Command = 0x34;
  453. data.VariableType = TemperatureVariableType.Buffer;
  454. AddDataToQueue(data);
  455. }
  456. #endregion
  457. #region Offset
  458. /// <summary>
  459. /// 设置温度
  460. /// </summary>
  461. /// <param name="id"></param>
  462. /// <param name="temperature"></param>
  463. /// <returns></returns>
  464. public void SetOffsetValue(byte id, double temperature)
  465. {
  466. TemperatureSendData data = new TemperatureSendData();
  467. data.Id = id;
  468. data.Type = 0;
  469. data.Command = 0x36;
  470. data.Data = GetOffsetBytes(temperature);
  471. TemperatureSendData readData = GetReadOffsetData(id);
  472. InsertDatasToQueue(data,readData);
  473. }
  474. /// <summary>
  475. /// 获取读取Offset数据
  476. /// </summary>
  477. /// <param name="id"></param>
  478. /// <returns></returns>
  479. private TemperatureSendData GetReadOffsetData(byte id)
  480. {
  481. TemperatureSendData data = new TemperatureSendData();
  482. data.Id = id;
  483. data.Type = 1;
  484. data.VariableName = "Offset";
  485. data.Command = 0x36;
  486. data.VariableType = TemperatureVariableType.SignedDecade;
  487. return data;
  488. }
  489. /// <summary>
  490. /// 读取Alarm状态
  491. /// </summary>
  492. /// <param name="id"></param>
  493. /// <param name="offset"></param>
  494. /// <returns></returns>
  495. public void ReadOffsetValue(byte id)
  496. {
  497. TemperatureSendData data=GetReadOffsetData(id);
  498. AddDataToQueue(data);
  499. }
  500. #endregion
  501. #region Control Operation Model
  502. /// <summary>
  503. /// 设置Control Operation模式
  504. /// </summary>
  505. /// <param name="id"></param>
  506. /// <param name="temperature"></param>
  507. /// <returns></returns>
  508. public void SetControlOperationModel(byte id, int controlOperationModel)
  509. {
  510. TemperatureSendData data = new TemperatureSendData();
  511. data.Id = id;
  512. data.Type = 0;
  513. data.Command = 0x39;
  514. data.Data = GetKiloBytes(controlOperationModel);
  515. TemperatureSendData readData=GetReadControlOperationData(id);
  516. InsertDatasToQueue(data, readData);
  517. }
  518. /// <summary>
  519. /// 获取读取操作模式的数据
  520. /// </summary>
  521. /// <param name="id"></param>
  522. /// <returns></returns>
  523. private TemperatureSendData GetReadControlOperationData(byte id)
  524. {
  525. TemperatureSendData data = new TemperatureSendData();
  526. data.Id = id;
  527. data.Type = 1;
  528. data.VariableName = "ControlOperationModel";
  529. data.Command = 0x39;
  530. data.VariableType = TemperatureVariableType.Kilo;
  531. return data;
  532. }
  533. /// <summary>
  534. /// 读取Control Operation Model
  535. /// </summary>
  536. /// <param name="id"></param>
  537. /// <param name="offset"></param>
  538. /// <returns></returns>
  539. public void ReadControlOperationModel(byte id)
  540. {
  541. TemperatureSendData data = GetReadControlOperationData(id);
  542. InsertDataToQueue(data);
  543. }
  544. #endregion
  545. #region PB Range
  546. /// <summary>
  547. /// 设置PB范围
  548. /// </summary>
  549. /// <param name="id"></param>
  550. /// <param name="temperature"></param>
  551. /// <returns></returns>
  552. public void SetPBRange(byte id, double pbrange)
  553. {
  554. TemperatureSendData data = new TemperatureSendData();
  555. data.Id = id;
  556. data.Type = 0;
  557. data.Command = 0x41;
  558. data.Data = GetDecadeBytes(pbrange);
  559. InsertDataToQueue(data);
  560. }
  561. /// <summary>
  562. /// 读取PB范围
  563. /// </summary>
  564. /// <param name="id"></param>
  565. /// <param name="pbrange"></param>
  566. /// <returns></returns>
  567. public void ReadPBRange(byte id)
  568. {
  569. TemperatureSendData data = new TemperatureSendData();
  570. data.Id = id;
  571. data.Type = 1;
  572. data.VariableName = "PBRange";
  573. data.Command = 0x41;
  574. data.VariableType = TemperatureVariableType.Decade;
  575. AddDataToQueue(data);
  576. }
  577. #endregion
  578. #region ARW
  579. /// <summary>
  580. /// 设置ARW范围
  581. /// </summary>
  582. /// <param name="id"></param>
  583. /// <param name="temperature"></param>
  584. /// <returns></returns>
  585. public void SetARWRange(byte id, double arwRange)
  586. {
  587. TemperatureSendData data = new TemperatureSendData();
  588. data.Id = id;
  589. data.Type = 0;
  590. data.Command = 0x42;
  591. data.Data = GetDecadeBytes(arwRange);
  592. InsertDataToQueue(data);
  593. }
  594. /// <summary>
  595. /// 读取Heat Exchanger温度
  596. /// </summary>
  597. /// <param name="id"></param>
  598. /// <param name="arwrange"></param>
  599. /// <returns></returns>
  600. public void ReadARWRange(byte id)
  601. {
  602. TemperatureSendData data = new TemperatureSendData();
  603. data.Id = id;
  604. data.Type = 1;
  605. data.VariableName = "ARWRange";
  606. data.Command = 0x42;
  607. data.VariableType = TemperatureVariableType.Decade;
  608. AddDataToQueue(data);
  609. }
  610. #endregion
  611. #region I constant
  612. /// <summary>
  613. /// 设置I Constant
  614. /// </summary>
  615. /// <param name="id"></param>
  616. /// <param name="temperature"></param>
  617. /// <returns></returns>
  618. public void SetIConstant(byte id, int iConstant)
  619. {
  620. TemperatureSendData data = new TemperatureSendData();
  621. data.Id = id;
  622. data.Type = 0;
  623. data.Command = 0x43;
  624. data.Data = GetKiloBytes(iConstant);
  625. InsertDataToQueue(data);
  626. }
  627. /// <summary>
  628. /// 读取Heat Exchanger温度
  629. /// </summary>
  630. /// <param name="id"></param>
  631. /// <param name="arwrange"></param>
  632. /// <returns></returns>
  633. public void ReadIConstant(byte id)
  634. {
  635. TemperatureSendData data = new TemperatureSendData();
  636. data.Id = id;
  637. data.Type = 1;
  638. data.VariableName = "IConstant";
  639. data.Command = 0x43;
  640. data.VariableType = TemperatureVariableType.Kilo;
  641. AddDataToQueue(data);
  642. }
  643. #endregion
  644. #region D constant
  645. /// <summary>
  646. /// 设置D Constant
  647. /// </summary>
  648. /// <param name="id"></param>
  649. /// <param name="temperature"></param>
  650. /// <returns></returns>
  651. public void SetDConstant(byte id, int dConstant)
  652. {
  653. TemperatureSendData data = new TemperatureSendData();
  654. data.Id = id;
  655. data.Type = 0;
  656. data.Command = 0x44;
  657. data.Data = GetDecadeBytes(dConstant);
  658. InsertDataToQueue(data);
  659. }
  660. /// <summary>
  661. /// 读取D Constant
  662. /// </summary>
  663. /// <param name="id"></param>
  664. /// <param name="arwrange"></param>
  665. /// <returns></returns>
  666. public void ReadDConstant(byte id)
  667. {
  668. TemperatureSendData data = new TemperatureSendData();
  669. data.Id = id;
  670. data.Type = 1;
  671. data.VariableName = "DConstant";
  672. data.Command = 0x44;
  673. data.VariableType = TemperatureVariableType.Decade;
  674. AddDataToQueue(data);
  675. }
  676. #endregion
  677. #region Output Ratio
  678. /// <summary>
  679. /// Output 比例
  680. /// </summary>
  681. /// <param name="id"></param>
  682. /// <param name="temperature"></param>
  683. /// <returns></returns>
  684. public void SetOutputRatio(byte id, int outputRatio)
  685. {
  686. TemperatureSendData data = new TemperatureSendData();
  687. data.Id = id;
  688. data.Type = 0;
  689. data.Command = 0x45;
  690. data.Data = GetKiloBytes(outputRatio);
  691. InsertDataToQueue(data);
  692. }
  693. /// <summary>
  694. /// 读取output比例
  695. /// </summary>
  696. /// <param name="id"></param>
  697. /// <param name="arwrange"></param>
  698. /// <returns></returns>
  699. public void ReadOutputRatio(byte id)
  700. {
  701. TemperatureSendData data = new TemperatureSendData();
  702. data.Id = id;
  703. data.Type = 1;
  704. data.VariableName = "OutputRatio";
  705. data.Command = 0x45;
  706. data.VariableType = TemperatureVariableType.Kilo;
  707. AddDataToQueue(data);
  708. }
  709. #endregion
  710. #region Heating Power upper limit
  711. /// <summary>
  712. /// Heating Power upper limit 比例
  713. /// </summary>
  714. /// <param name="id"></param>
  715. /// <param name="temperature"></param>
  716. /// <returns></returns>
  717. public void SetHeatingPowerUpperLimit(byte id, int upperLimit)
  718. {
  719. TemperatureSendData data = new TemperatureSendData();
  720. data.Id = id;
  721. data.Type = 0;
  722. data.Command = 0x46;
  723. data.Data = GetKiloBytes(upperLimit);
  724. InsertDataToQueue(data);
  725. }
  726. /// <summary>
  727. /// 读取output比例
  728. /// </summary>
  729. /// <param name="id"></param>
  730. /// <param name="arwrange"></param>
  731. /// <returns></returns>
  732. public void ReadHeatingPowerUpperLimit(byte id)
  733. {
  734. TemperatureSendData data = new TemperatureSendData();
  735. data.Id = id;
  736. data.Type = 1;
  737. data.VariableName = "HeatingPowerUpperLimit";
  738. data.Command = 0x46;
  739. data.VariableType = TemperatureVariableType.Kilo;
  740. AddDataToQueue(data);
  741. }
  742. #endregion
  743. #region Cooling Power upper limit
  744. /// <summary>
  745. /// Heating Power upper limit 比例
  746. /// </summary>
  747. /// <param name="id"></param>
  748. /// <param name="temperature"></param>
  749. /// <returns></returns>
  750. public void SetCoolingPowerUpperLimit(byte id, int upperLimit)
  751. {
  752. TemperatureSendData data = new TemperatureSendData();
  753. data.Id = id;
  754. data.Type = 0;
  755. data.Command = 0x47;
  756. data.Data = GetKiloBytes(upperLimit);
  757. InsertDataToQueue(data);
  758. }
  759. /// <summary>
  760. /// 读取output比例
  761. /// </summary>
  762. /// <param name="id"></param>
  763. /// <param name="arwrange"></param>
  764. /// <returns></returns>
  765. public void ReadCoolingPowerUpperLimit(byte id)
  766. {
  767. TemperatureSendData data = new TemperatureSendData();
  768. data.Id = id;
  769. data.Type = 1;
  770. data.VariableName = "CoolingPowerUpperLimit";
  771. data.Command = 0x47;
  772. data.VariableType = TemperatureVariableType.Kilo;
  773. AddDataToQueue(data);
  774. }
  775. #endregion
  776. #region Saving RAM to EEPROM
  777. /// <summary>
  778. /// 将RAM保存至EEPROM
  779. /// </summary>
  780. /// <param name="id"></param>
  781. /// <param name="temperature"></param>
  782. /// <returns></returns>
  783. public void SaveRAMToEEPROM(byte id)
  784. {
  785. TemperatureSendData data = new TemperatureSendData();
  786. data.Id = id;
  787. data.Type = 0;
  788. data.Command = 0x48;
  789. data.Data = new byte[] { };
  790. InsertDataToQueue(data);
  791. }
  792. #endregion
  793. /// <summary>
  794. /// 读取千单位数据
  795. /// </summary>
  796. /// <param name="id"></param>
  797. /// <param name="command"></param>
  798. /// <param name="param"></param>
  799. /// <returns></returns>
  800. private bool ReadKiloParam(byte id,byte command,out int param,int responseLength=12)
  801. {
  802. param = 0;
  803. try
  804. {
  805. byte[] response = AfterSendDataWithResponse(id, command,responseLength);
  806. if (response==null)
  807. {
  808. return false;
  809. }
  810. //解析
  811. if (response[0] == SOH && response[11] == CR && response[3] == command)
  812. {
  813. if (response[1] == GetSendByteData(id))
  814. {
  815. byte[] byt = new byte[4];
  816. Array.Copy(response, 4, byt, 0, byt.Length);
  817. param = GetOriginalData(byt[0]) * 1000 + GetOriginalData(byt[1]) * 100 + GetOriginalData(byt[2]) * 10 + GetOriginalData(byt[3]);
  818. return true;
  819. }
  820. else
  821. {
  822. string msg = $"receive id {GetOriginalData(response[1])} is not matched with command id {id}";
  823. WriteErrorMsg(msg, false);
  824. return false;
  825. }
  826. }
  827. else
  828. {
  829. string msg = "response data invalid";
  830. WriteErrorMsg(msg, false);
  831. return false;
  832. }
  833. }
  834. catch (Exception ex)
  835. {
  836. WriteErrorMsg(ex.Message);
  837. return false;
  838. }
  839. }
  840. /// <summary>
  841. /// 根据十单位数据
  842. /// </summary>
  843. /// <param name="id"></param>
  844. /// <param name="command"></param>
  845. /// <param name="decadeValue"></param>
  846. /// <returns></returns>
  847. private bool ReadDecadeParam(byte id, byte command, out double decadeValue, int responseLength = 12)
  848. {
  849. decadeValue = 0;
  850. byte[] response = AfterSendDataWithResponse(id, command,responseLength);
  851. if(response==null)
  852. {
  853. return false;
  854. }
  855. //解析
  856. if (response[0] == SOH && response[11] == CR && response[3] == command)
  857. {
  858. if (response[1] == GetSendByteData(id))
  859. {
  860. byte[] tmpData = new byte[4];
  861. Array.Copy(response, 4, tmpData, 0, tmpData.Length);
  862. decadeValue = GetOriginalData(tmpData[0]) * 10 + GetOriginalData(tmpData[1]) + GetOriginalData(tmpData[2]) * 0.1 + GetOriginalData(tmpData[3]) * 0.01;
  863. return true;
  864. }
  865. else
  866. {
  867. string msg = $"receive id {GetOriginalData(response[1])} is not matched with command id {id}";
  868. WriteErrorMsg(msg, false);
  869. return false;
  870. }
  871. }
  872. else
  873. {
  874. string msg = "response data invalid";
  875. WriteErrorMsg(msg,false);
  876. return false;
  877. }
  878. }
  879. /// <summary>
  880. /// 根据有符号十单位数据
  881. /// </summary>
  882. /// <param name="id"></param>
  883. /// <param name="command"></param>
  884. /// <param name="signedDecadeValue"></param>
  885. /// <returns></returns>
  886. private bool ReadSignedDecadeParam(byte id, byte command, out double signedDecadeValue, int responseLength = 12)
  887. {
  888. signedDecadeValue = 0;
  889. byte[] response = AfterSendDataWithResponse(id, command, responseLength);
  890. if (response == null)
  891. {
  892. return false;
  893. }
  894. string err = "response data invalid";
  895. //解析
  896. if (response[0] == SOH && response[11] == CR && response[3] == command)
  897. {
  898. if (response[1] == GetSendByteData(id))
  899. {
  900. byte[] byt = new byte[4];
  901. Array.Copy(response, 4, byt, 0, byt.Length);
  902. double tmp = GetOriginalData(byt[1]) + GetOriginalData(byt[2]) * 0.1 + GetOriginalData(byt[3]) * 0.01;
  903. if (byt[0] == MINUS_FLAG)
  904. {
  905. signedDecadeValue = -tmp;
  906. return true;
  907. }
  908. else if (byt[0] == ADD_FLAG)
  909. {
  910. signedDecadeValue = tmp;
  911. return true;
  912. }
  913. else
  914. {
  915. WriteErrorMsg(err, false);
  916. return false;
  917. }
  918. }
  919. else
  920. {
  921. string msg = $"receive id {GetOriginalData(response[1])} is not matched with command id {id}";
  922. WriteErrorMsg(msg, false);
  923. return false;
  924. }
  925. }
  926. else
  927. {
  928. WriteErrorMsg(err, false);
  929. return false;
  930. }
  931. }
  932. /// <summary>
  933. /// 根据数组数据
  934. /// </summary>
  935. /// <param name="id"></param>
  936. /// <param name="command"></param>
  937. /// <param name="signedDecadeValue"></param>
  938. /// <returns></returns>
  939. private bool ReadBufferParam(byte id, byte command, out byte[] buffer, int responseLength = 12)
  940. {
  941. buffer = null;
  942. byte[] response = AfterSendDataWithResponse(id, command, responseLength);
  943. if (response == null)
  944. {
  945. return false;
  946. }
  947. //解析
  948. if (response[0] == SOH && response[responseLength-1] == CR && response[3] == command)
  949. {
  950. if (response[1] == GetSendByteData(id))
  951. {
  952. buffer = new byte[responseLength - 8];
  953. Array.Copy(response, 4, buffer, 0, buffer.Length);
  954. return true;
  955. }
  956. else
  957. {
  958. string msg = $"receive id {GetOriginalData(response[1])} is not matched with command id {id}";
  959. WriteErrorMsg(msg, false);
  960. return false;
  961. }
  962. }
  963. else
  964. {
  965. string err = "response data invalid";
  966. WriteErrorMsg(err,false);
  967. return false;
  968. }
  969. }
  970. /// <summary>
  971. /// 设置操作
  972. /// </summary>
  973. /// <param name="id"></param>
  974. /// <param name="command"></param>
  975. /// <param name="byt"></param>
  976. /// <returns></returns>
  977. private bool SettingOperation(byte id, byte command, byte[] byt)
  978. {
  979. ClearPreCache();
  980. byte ut = GetSendByteData(id);
  981. byte[] data = new byte[byt.Length + 8];
  982. data[0] = SOH;
  983. data[1] = ut;
  984. data[2] = STX;
  985. data[3] = command;
  986. if (byt != null && byt.Length != 0)
  987. {
  988. Array.Copy(byt, 0, data, 4, byt.Length);
  989. }
  990. data[data.Length - 4] = ETX;
  991. data[data.Length - 3] = 0;
  992. data[data.Length - 2] = 0;
  993. data[data.Length - 1] = CR;
  994. //检验
  995. byte[] checksumData = new byte[data.Length - 5];
  996. //从数据第2位至ETX前所有数组
  997. Array.Copy(data, 1, checksumData, 0, checksumData.Length);
  998. byte[] checkSumByte = CalculateCheckSum(checksumData);
  999. Array.Copy(checkSumByte, 0, data, data.Length - 3, checkSumByte.Length);
  1000. _serialPort.Write(data, 0, data.Length);
  1001. WriteInfoMsg(1, data);
  1002. //接收
  1003. byte[] response = ReadData(id,command,3);
  1004. if (response != null)
  1005. {
  1006. if (response[0] == ACK && response[2] == CR && response[1] == ut)
  1007. {
  1008. return true;
  1009. }
  1010. else
  1011. {
  1012. string err = "response data invalid";
  1013. WriteErrorMsg(err, false);
  1014. return false;
  1015. }
  1016. }
  1017. else
  1018. {
  1019. return false;
  1020. }
  1021. }
  1022. /// <summary>
  1023. /// 发送数据后获取数组
  1024. /// </summary>
  1025. /// <param name="id"></param>
  1026. /// <param name="command"></param>
  1027. /// <returns></returns>
  1028. private byte[] AfterSendDataWithResponse(byte id,byte command,int responseLength=12)
  1029. {
  1030. try
  1031. {
  1032. ClearPreCache();
  1033. byte ut = GetSendByteData(id);
  1034. byte[] data = new byte[7] { SOH, ut, ENQ, command, 0, 0, CR };
  1035. //检验
  1036. byte[] checksumData = new byte[data.Length - 4];
  1037. //从数据第2位至ETX前所有数组
  1038. Array.Copy(data, 1, checksumData, 0, checksumData.Length);
  1039. byte[] checkSumByte = CalculateCheckSum(checksumData);
  1040. Array.Copy(checkSumByte, 0, data, data.Length - 3, checkSumByte.Length);
  1041. _serialPort.Write(data, 0, data.Length);
  1042. WriteInfoMsg(1, data);
  1043. //接收
  1044. byte[] response = ReadData(id,command,responseLength);
  1045. if (response == null)
  1046. {
  1047. return null;
  1048. }
  1049. //ack
  1050. byte[] ack = new byte[] { ACK, ut, CR };
  1051. _serialPort.Write(ack, 0, ack.Length);
  1052. WriteInfoMsg(1, ack);
  1053. return response;
  1054. }
  1055. catch(Exception ex)
  1056. {
  1057. _connected = false;
  1058. WriteErrorMsg(ex.Message);
  1059. return null;
  1060. }
  1061. }
  1062. /// <summary>
  1063. /// 计算获取检验和数组
  1064. /// </summary>
  1065. /// <param name="checkSumData"></param>
  1066. /// <returns></returns>
  1067. private byte[] CalculateCheckSum(byte[] checkSumData)
  1068. {
  1069. short checksum = 0;
  1070. for(int i=0;i<checkSumData.Length;i++)
  1071. {
  1072. checksum += checkSumData[i];
  1073. }
  1074. byte[] byt=BitConverter.GetBytes(checksum);
  1075. byte[] data = new byte[2];
  1076. data[0] = GetSendByteData((byte)(byt[0]/16));
  1077. data[1] = GetSendByteData((byte)(byt[0]&0x0F));
  1078. return data;
  1079. }
  1080. /// <summary>
  1081. /// 获取温度数组(10|1|0.1|0.01)
  1082. /// </summary>
  1083. /// <param name="temperature"></param>
  1084. /// <returns></returns>
  1085. private byte[] GetDecadeBytes(double temperature)
  1086. {
  1087. byte decade = GetSendByteData((byte)Math.Floor(temperature / 10));
  1088. byte unit = GetSendByteData((byte)Math.Floor(temperature % 10));
  1089. byte digital = GetSendByteData((byte)Math.Floor(temperature * 10 % 10));
  1090. return new byte[4] { decade, unit, digital, ADD_FLAG };
  1091. }
  1092. /// <summary>
  1093. /// 获取Offset数组(正/负|1|0.1|0.01)
  1094. /// </summary>
  1095. /// <param name="temperature"></param>
  1096. /// <returns></returns>
  1097. private byte[] GetOffsetBytes(double temperature)
  1098. {
  1099. byte decade = temperature>0?ADD_FLAG:MINUS_FLAG;
  1100. byte unit = GetSendByteData((byte)Math.Floor(temperature % 10));
  1101. byte digital = GetSendByteData((byte)Math.Floor(temperature * 10 % 10));
  1102. byte digital2 = GetSendByteData((byte)Math.Floor(temperature * 100 % 10));
  1103. return new byte[4] { decade, unit, digital, digital2 };
  1104. }
  1105. /// <summary>
  1106. /// 获取Control Operation Model(1000|100|10|1)
  1107. /// </summary>
  1108. /// <param name="controlOperationModel"></param>
  1109. /// <returns></returns>
  1110. private byte[] GetKiloBytes(int controlOperationModel)
  1111. {
  1112. byte kilo= GetSendByteData((byte)(controlOperationModel / 1000));
  1113. byte hundred = GetSendByteData((byte)(controlOperationModel %1000/ 100));
  1114. byte decade = GetSendByteData((byte)(controlOperationModel %100/ 10));
  1115. byte unit = GetSendByteData((byte)(controlOperationModel % 10));
  1116. return new byte[4] { kilo, hundred, decade, unit };
  1117. }
  1118. /// <summary>
  1119. /// 获取发送位数据
  1120. /// </summary>
  1121. /// <param name="originalData"></param>
  1122. /// <returns></returns>
  1123. private byte GetSendByteData(byte originalData)
  1124. {
  1125. return (byte)(ADD_FLAG + originalData);
  1126. }
  1127. /// <summary>
  1128. /// 解析源数据
  1129. /// </summary>
  1130. /// <param name="receivedData"></param>
  1131. /// <returns></returns>
  1132. private byte GetOriginalData(byte receivedData)
  1133. {
  1134. return (byte)(receivedData - ADD_FLAG);
  1135. }
  1136. /// <summary>
  1137. /// 读取数据
  1138. /// </summary>
  1139. /// <param name="length"></param>
  1140. /// <returns></returns>
  1141. private byte[] ReadData(byte id,byte command ,int length)
  1142. {
  1143. byte[] response=new byte[length];
  1144. DateTime dt = DateTime.Now;
  1145. int count = 0;
  1146. while (true)
  1147. {
  1148. int bytLength = _serialPort.BytesToRead;
  1149. if (bytLength > 0)
  1150. {
  1151. byte[] bytes = new byte[bytLength];
  1152. _serialPort.Read(bytes,0,bytes.Length);
  1153. WriteInfoMsg(0, bytes);
  1154. if (bytLength + count >= length)
  1155. {
  1156. Array.Copy(bytes, 0, response, count, length-count);
  1157. break;
  1158. }
  1159. else
  1160. {
  1161. Array.Copy(bytes, 0, response, count, bytLength);
  1162. }
  1163. count += bytLength;
  1164. }
  1165. if (DateTime.Now.Subtract(dt).TotalMilliseconds >= _receiveTimeOut)
  1166. {
  1167. string err =$"receive id {id} command {command.ToString("X2")} timeout {length}";
  1168. TemperatureConfigManager.Instance.UpdataTCPowerConnectDic(_name + '-' + id.ToString(),false);//读取数据超时认为TC断联
  1169. WriteErrorMsg(err,false);
  1170. return null;
  1171. }
  1172. else
  1173. {
  1174. TemperatureConfigManager.Instance.UpdataTCPowerConnectDic(_name + '-' + id.ToString(),true);
  1175. }
  1176. Thread.Sleep(2);
  1177. }
  1178. WriteInfoMsg(0, response);
  1179. return response;
  1180. }
  1181. /// <summary>
  1182. /// 记录错误信息
  1183. /// </summary>
  1184. /// <param name="msg"></param>
  1185. private void WriteErrorMsg(string msg,bool disConnected=true)
  1186. {
  1187. if (disConnected)
  1188. {
  1189. _connected = false;
  1190. _offlineDateTime = DateTime.Now;
  1191. }
  1192. bool enableLog = false;
  1193. if (SC.ContainsItem("Log.EnableTemperatureLog"))
  1194. {
  1195. enableLog = SC.GetValue<bool>("Log.EnableTemperatureLog");
  1196. }
  1197. if (enableLog)
  1198. {
  1199. if (_errorMsg != msg)
  1200. {
  1201. _errorMsg = msg;
  1202. LOG.WriteBackgroundLog(eEvent.ERR_TEMPERATURE, _name, msg);
  1203. }
  1204. }
  1205. }
  1206. /// <summary>
  1207. /// 写日志
  1208. /// </summary>
  1209. /// <param name="bytes"></param>
  1210. private void WriteInfoMsg(int logType, byte[] bytes)
  1211. {
  1212. bool enableLog = false;
  1213. if (SC.ContainsItem("Log.EnableTemperatureLog"))
  1214. {
  1215. enableLog = SC.GetValue<bool>("Log.EnableTemperatureLog");
  1216. }
  1217. if (enableLog)
  1218. {
  1219. string str = string.Join(" ", Array.ConvertAll(bytes, x => x.ToString("X2")));
  1220. string type = logType == 0 ? "receive" : "send";
  1221. LOG.WriteBackgroundLog(eEvent.INFO_TEMPERATURE, _name, $"{type} {str}");
  1222. }
  1223. }
  1224. /// <summary>
  1225. /// 写日志
  1226. /// </summary>
  1227. /// <param name="bytes"></param>
  1228. private void WriteInfoMsg(int logType, string str)
  1229. {
  1230. bool enableLog = false;
  1231. if (SC.ContainsItem("Log.EnableTemperatureLog"))
  1232. {
  1233. enableLog = SC.GetValue<bool>("Log.EnableTemperatureLog");
  1234. }
  1235. if (enableLog)
  1236. {
  1237. string type = logType == 0 ? "receive" : "send";
  1238. LOG.WriteBackgroundLog(eEvent.INFO_TEMPERATURE, _name, $"{type} {str}");
  1239. }
  1240. }
  1241. /// <summary>
  1242. /// 清除前面的缓存
  1243. /// </summary>
  1244. private void ClearPreCache()
  1245. {
  1246. while (_serialPort.BytesToRead != 0)
  1247. {
  1248. byte[] bytes = new byte[_serialPort.BytesToRead];
  1249. _serialPort.Read(bytes, 0, bytes.Length);
  1250. }
  1251. }
  1252. }
  1253. /// <summary>
  1254. /// 发送数据类
  1255. /// </summary>
  1256. internal class TemperatureSendData
  1257. {
  1258. public byte Id { get; set; }
  1259. public byte Command { get; set; }
  1260. public byte[] Data { get; set; }
  1261. /// <summary>
  1262. /// 0-set,1-get
  1263. /// </summary>
  1264. public byte Type { get; set; }
  1265. /// <summary>
  1266. /// 变量
  1267. /// </summary>
  1268. public string VariableName { get; set; }
  1269. /// <summary>
  1270. /// 变量数值
  1271. /// </summary>
  1272. public object VariableValue { get; set; }
  1273. /// <summary>
  1274. /// 变量类型(0-十位数据,1-千位数据,2-数组,3-有符号十位数据)
  1275. /// </summary>
  1276. public TemperatureVariableType VariableType { get; set; }
  1277. }
  1278. }