LinMotSerialDevice.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. using Aitex.Core.RT.Log;
  2. using Aitex.Core.RT.OperationCenter;
  3. using Aitex.Core.RT.SCCore;
  4. using Aitex.Core.Util;
  5. using DocumentFormat.OpenXml.ExtendedProperties;
  6. using System;
  7. using System.Collections.Concurrent;
  8. using System.Collections.Generic;
  9. using System.IO.Ports;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading;
  13. using System.Threading.Tasks;
  14. namespace MECF.Framework.Common.Device.LinMot
  15. {
  16. public enum LinMotOperation
  17. {
  18. None = 0,
  19. SwitchOn = 1,
  20. SwitchOff = 2,
  21. Home = 3,
  22. Curve = 4,
  23. GoToInitialPosition = 5,
  24. CurveGotoInitialPosition = 6,
  25. Reset=7,
  26. ClearError=8,
  27. StartCurve=9,
  28. StopMotor=10,
  29. ControlWordGoToPosition=11,
  30. Freeze=12,
  31. StartVAIGoToPosition=13,
  32. ReadStatus=99
  33. }
  34. public class LinMotSerialDevice
  35. {
  36. #region 常量
  37. /// <summary>
  38. /// 开始标识
  39. /// </summary>
  40. private const byte START_FLAG = 0X01;
  41. /// <summary>
  42. /// 结束标识
  43. /// </summary>
  44. private const byte END_FLAG = 0x04;
  45. /// <summary>
  46. /// 最小长度
  47. /// </summary>
  48. private const byte MIN_LENGTH = 5;
  49. /// <summary>
  50. /// 最大长度(1(Header)+1(ID)+1(Length)+3(StartData+Msg High+Msg Low)+n(Data最大63)+1(End))
  51. /// </summary>
  52. private const byte MAX_LENGTH = 70;
  53. /// <summary>
  54. /// 缓存最大
  55. /// </summary>
  56. private const int BUFFER_LENGTH = 65535;
  57. #endregion
  58. #region 内部变量
  59. /// <summary>
  60. /// 串口
  61. /// </summary>
  62. private SerialPort _serialPort;
  63. /// <summary>
  64. /// 缓存
  65. /// </summary>
  66. private byte[] _buffer = new byte[BUFFER_LENGTH];
  67. /// <summary>
  68. /// 缓存锁
  69. /// </summary>
  70. private object _lock = new object();
  71. /// <summary>
  72. /// 偏移量
  73. /// </summary>
  74. private int offset = 0;
  75. /// <summary>
  76. /// 数量
  77. /// </summary>
  78. private int count = 0;
  79. /// <summary>
  80. /// 定时任务
  81. /// </summary>
  82. private PeriodicJob _periodJob;
  83. /// <summary>
  84. /// 发送定时任务
  85. /// </summary>
  86. private PeriodicJob _sendPeriodJob;
  87. /// <summary>
  88. /// 连接状态
  89. /// </summary>
  90. private bool _connected;
  91. /// <summary>
  92. /// 发送队列
  93. /// </summary>
  94. private ConcurrentQueue<byte[]> _sendOperationQueue = new ConcurrentQueue<byte[]>();
  95. /// <summary>
  96. /// 模块名称
  97. /// </summary>
  98. private string _name;
  99. /// <summary>
  100. /// 支持重连
  101. /// </summary>
  102. private bool _reconnect;
  103. /// <summary>
  104. /// 错误
  105. /// </summary>
  106. private string _errmsg;
  107. /// <summary>
  108. /// 离线时间
  109. /// </summary>
  110. private DateTime _offlineDateTime = DateTime.Now;
  111. /// <summary>
  112. /// 首次连接成功
  113. /// </summary>
  114. private bool _isFirstConnected = false;
  115. /// <summary>
  116. /// 自增锁
  117. /// </summary>
  118. private object _autoCountLock = new object();
  119. /// <summary>
  120. /// 自动增加计数
  121. /// </summary>
  122. private byte _autoCount = 0;
  123. #endregion
  124. #region 属性
  125. /// <summary>
  126. /// 连接状态
  127. /// </summary>
  128. public bool Connected
  129. {
  130. get { return _connected; }
  131. set { _connected = value; }
  132. }
  133. #endregion
  134. /// <summary>
  135. /// 初始化
  136. /// </summary>
  137. /// <param name="portName"></param>
  138. /// <param name="baudRate"></param>
  139. /// <param name="stopBits"></param>
  140. /// <param name="dataBits"></param>
  141. /// <param name="parity"></param>
  142. public LinMotSerialDevice(string name, string portName, int baudRate = 9600, StopBits stopBits = StopBits.One, int dataBits = 8, Parity parity = Parity.None, bool reconnect = false)
  143. {
  144. _serialPort = new SerialPort();
  145. _serialPort.BaudRate = baudRate;
  146. _serialPort.StopBits = stopBits;
  147. _serialPort.DataBits = dataBits;
  148. _serialPort.Parity = parity;
  149. _serialPort.PortName = portName;
  150. _serialPort.DataReceived += SerialPort_DataReceived;
  151. _serialPort.ErrorReceived += SerialPort_ErrorReceived;
  152. _name = name;
  153. _reconnect = reconnect;
  154. _periodJob = new PeriodicJob(50, OnTimer, $"{_name}_Analyser", false, true);
  155. _sendPeriodJob = new PeriodicJob(50, OnSenderTimer, $"{_name}_Sender", false, true);
  156. }
  157. /// <summary>
  158. /// 初始化
  159. /// </summary>
  160. public void Initialize()
  161. {
  162. _periodJob.Start();
  163. _sendPeriodJob.Start();
  164. }
  165. /// <summary>
  166. /// 启动
  167. /// </summary>
  168. public void Start()
  169. {
  170. if (!_connected)
  171. {
  172. try
  173. {
  174. _serialPort.Open();
  175. LOG.WriteLog(eEvent.INFO_LINMOT, _name, $"connect port[{_serialPort.PortName}] success");
  176. _connected = true;
  177. }
  178. catch (Exception ex)
  179. {
  180. WriteErrorMsg(ex.Message);
  181. }
  182. if (!_isFirstConnected)
  183. {
  184. _isFirstConnected = true;
  185. }
  186. }
  187. }
  188. /// <summary>
  189. /// 关闭
  190. /// </summary>
  191. public void Close()
  192. {
  193. try
  194. {
  195. _connected = false;
  196. _serialPort.Close();
  197. _periodJob.Stop();
  198. }
  199. catch (Exception ex)
  200. {
  201. WriteErrorMsg(ex.Message);
  202. }
  203. }
  204. /// <summary>
  205. /// 定时器
  206. /// </summary>
  207. /// <returns></returns>
  208. private bool OnTimer()
  209. {
  210. lock (_lock)
  211. {
  212. if (count < MIN_LENGTH)
  213. {
  214. return true;
  215. }
  216. }
  217. try
  218. {
  219. var result = CheckValid();
  220. if (result.Item3)
  221. {
  222. lock (_lock)
  223. {
  224. int startIndex = result.Item1;
  225. int endIndex = result.Item2;
  226. byte[] byt = new byte[endIndex - startIndex + 1];
  227. Array.Copy(_buffer, startIndex, byt, 0, byt.Length);
  228. Array.Copy(_buffer, endIndex + 1, _buffer, 0, count - endIndex - 1);
  229. count = count - endIndex - 1;
  230. offset = count;
  231. _buffer[count] = 0;
  232. _buffer[count + 1] = 0;
  233. _buffer[count + 2] = 0;
  234. _buffer[count + 3] = 0;
  235. Analyse(byt);
  236. }
  237. }
  238. else
  239. {
  240. lock (_lock)
  241. {
  242. int startIndex = result.Item1;
  243. int endIndex = result.Item2;
  244. if (startIndex == -1)
  245. {
  246. _buffer = new byte[BUFFER_LENGTH];
  247. offset = 0;
  248. count = 0;
  249. }
  250. else if (startIndex > 0)
  251. {
  252. Array.Copy(_buffer, startIndex, _buffer, 0, count - startIndex);
  253. count = count - startIndex;
  254. offset = count;
  255. }
  256. else if (endIndex == -1 && count > MAX_LENGTH)//一直找不到结束标识,长度超过最大长度
  257. {
  258. //仅清除第一个StartFlag
  259. Array.Copy(_buffer, 1, _buffer, 0, count - 1);
  260. count = count - 1;
  261. offset = count;
  262. }
  263. }
  264. }
  265. }
  266. catch (Exception ex)
  267. {
  268. LOG.WriteLog(eEvent.ERR_LINMOT, _name, ex.StackTrace);
  269. }
  270. return true;
  271. }
  272. /// <summary>
  273. /// 发送定时器
  274. /// </summary>
  275. /// <returns></returns>
  276. private bool OnSenderTimer()
  277. {
  278. if(!_isFirstConnected)
  279. {
  280. return true;
  281. }
  282. if (!_connected)
  283. {
  284. if (_sendOperationQueue.Count != 0)
  285. {
  286. ClearSendQueue();
  287. }
  288. if (_reconnect)
  289. {
  290. Start();
  291. }
  292. else
  293. {
  294. _periodJob.Stop();
  295. }
  296. return true;
  297. }
  298. else
  299. {
  300. int queueCount = _sendOperationQueue.Count;
  301. if (_sendOperationQueue.Count != 0)
  302. {
  303. WriteInfoMsg(1, $"start send buffer queue length {queueCount}");
  304. if (_sendOperationQueue.TryDequeue(out byte[] sendBuffer))
  305. {
  306. try
  307. {
  308. WriteInfoMsg(1, $"start send buffer get queue data");
  309. _serialPort.Write(sendBuffer, 0, sendBuffer.Length);
  310. WriteInfoMsg(1, sendBuffer);
  311. WriteInfoMsg(1, $"send buffer queue length {queueCount}");
  312. }
  313. catch (Exception ex)
  314. {
  315. WriteErrorMsg(ex.Message);
  316. }
  317. }
  318. }
  319. }
  320. return true;
  321. }
  322. /// <summary>
  323. /// 清空发送队列
  324. /// </summary>
  325. private void ClearSendQueue()
  326. {
  327. try
  328. {
  329. while(_sendOperationQueue.Count!=0)
  330. {
  331. _sendOperationQueue.TryDequeue(out var result);
  332. }
  333. }
  334. catch
  335. {
  336. }
  337. }
  338. /// <summary>
  339. /// 校验
  340. /// </summary>
  341. /// <returns></returns>
  342. private (int, int, bool) CheckValid()
  343. {
  344. int startIndex = -1;
  345. int endIndex = -1;
  346. bool result = false;
  347. if(count<MIN_LENGTH)
  348. {
  349. return (-1, -1, false);
  350. }
  351. int dataLength = 0;
  352. for (int i = 0; i < count; i++)
  353. {
  354. if (_buffer[i] == START_FLAG && startIndex == -1)
  355. {
  356. startIndex = i;
  357. dataLength = _buffer[2];
  358. }
  359. else if (_buffer[i] == END_FLAG)
  360. {
  361. if (i == dataLength + 3)
  362. {
  363. endIndex = i;
  364. break;
  365. }
  366. }
  367. }
  368. if (endIndex > startIndex)
  369. {
  370. result = true;
  371. }
  372. return (startIndex, endIndex, result);
  373. }
  374. /// <summary>
  375. /// 解析标准包
  376. /// </summary>
  377. /// <param name="byt"></param>
  378. private void Analyse(byte[] byt)
  379. {
  380. if (byt.Length < 19)
  381. {
  382. return;
  383. }
  384. byte id = byt[1];//Id
  385. short statusWord = BitConverter.ToInt16(byt,7);//7状态字高位 8状态字低位
  386. short errorCode=BitConverter.ToInt16(byt,11);//11错误码高位 12错误码低位
  387. int currentPosition = BitConverter.ToInt32(byt, 15);
  388. string _linmotDeviceModuleName = LinMotDeviceConfigManager.Instance.GetModuleNameByAddress(_name, id);
  389. if (!string.IsNullOrEmpty(_linmotDeviceModuleName))
  390. {
  391. LinMotDeviceConfigManager.Instance.UpdateModuleData(_linmotDeviceModuleName, statusWord, errorCode, currentPosition);
  392. }
  393. }
  394. /// <summary>
  395. /// 出现错误
  396. /// </summary>
  397. /// <param name="sender"></param>
  398. /// <param name="e"></param>
  399. private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
  400. {
  401. LOG.WriteLog(eEvent.ERR_LINMOT, _name, e.EventType.ToString());
  402. }
  403. /// <summary>
  404. /// 串口接收
  405. /// </summary>
  406. /// <param name="sender"></param>
  407. /// <param name="e"></param>
  408. private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
  409. {
  410. byte[] readBuffer = new byte[_serialPort.BytesToRead];
  411. int readCount = _serialPort.Read(readBuffer, 0, readBuffer.Length);
  412. if (readCount == 0)
  413. {
  414. return;
  415. }
  416. WriteInfoMsg(0,readBuffer);
  417. lock (_lock)
  418. {
  419. Buffer.BlockCopy(readBuffer, 0, _buffer, offset, readCount);
  420. offset = offset + readCount;
  421. count = offset;
  422. }
  423. }
  424. /// <summary>
  425. /// 发送指令
  426. /// </summary>
  427. /// <param name="id"></param>
  428. /// <param name="operation"></param>
  429. public bool SendOperation(byte id,LinMotOperation operation)
  430. {
  431. if (_connected)
  432. {
  433. byte[] bytes = GenerateOperationBytes(id, operation);
  434. _sendOperationQueue.Enqueue(bytes);
  435. return true;
  436. }
  437. else
  438. {
  439. WriteErrorMsg($"{_name} is not connected");
  440. return false;
  441. }
  442. }
  443. /// <summary>
  444. /// 发送Curve指令
  445. /// </summary>
  446. /// <param name="id"></param>
  447. /// <param name="curveCount"></param>
  448. /// <param name="curveId"></param>
  449. /// <param name="timeScale"></param>
  450. /// <param name="curveOffset"></param>
  451. /// <param name="amplitudeScale"></param>
  452. public bool SendCurveOperation(byte id,ushort curveId,ushort timeScale,int curveOffset=0,short amplitudeScale=100)
  453. {
  454. if (_connected)
  455. {
  456. byte[] curveIdByt = BitConverter.GetBytes(curveId);
  457. byte[] curveOffsetByte = BitConverter.GetBytes(curveOffset);
  458. //timeScal--unit 0.01%
  459. byte[] timeScaleByt = BitConverter.GetBytes((ushort)(timeScale * 100));
  460. //amplitudeScale--unit 0.1%
  461. byte[] amplitudeScaleByte = BitConverter.GetBytes((short)(amplitudeScale * 10));
  462. GenerateAutoCount();
  463. byte[] byt = new byte[] { 0x01, id, 0x0F, 0x02, 0x00, 0x02, (byte)(0x40 | _autoCount), 0x04, curveIdByt[0], curveIdByt[1],curveOffsetByte[0], curveOffsetByte[1],
  464. curveOffsetByte[2], curveOffsetByte[3], timeScaleByt[0], timeScaleByt[1], amplitudeScaleByte[0], amplitudeScaleByte[1], 0x04 };
  465. _sendOperationQueue.Enqueue(byt);
  466. string str = string.Join(" ", Array.ConvertAll(byt, x => x.ToString("X2")));
  467. LOG.WriteBackgroundLog(eEvent.INFO_LINMOT, _name, $"curve operation {str}");
  468. return true;
  469. }
  470. else
  471. {
  472. WriteErrorMsg($"{_name} is not connected");
  473. return false;
  474. }
  475. }
  476. /// <summary>
  477. /// 发送CommandTable
  478. /// </summary>
  479. /// <param name="id"></param>
  480. /// <param name="curveCount"></param>
  481. /// <param name="entryId"></param>
  482. /// <returns></returns>
  483. public bool SendCommandTableOpertaion(byte id, short entryId=0)
  484. {
  485. if (_connected)
  486. {
  487. byte[] entryIdByt = BitConverter.GetBytes(entryId);
  488. GenerateAutoCount();
  489. byte[] byt = new byte[] { 0x01, id, 0x07, 0x02, 0x00, 0x02, (byte)(0x00 | _autoCount), 0x20, entryIdByt[0], entryIdByt[1], 0x04 };
  490. _sendOperationQueue.Enqueue(byt);
  491. string str = string.Join(" ", Array.ConvertAll(byt, x => x.ToString("X2")));
  492. LOG.WriteBackgroundLog(eEvent.INFO_LINMOT, _name, $"command table {str}");
  493. return true;
  494. }
  495. else
  496. {
  497. WriteErrorMsg($"{_name} is not connected");
  498. return false;
  499. }
  500. }
  501. /// <summary>
  502. ///
  503. /// </summary>
  504. /// <param name="id"></param>
  505. /// <param name="lowByte"></param>
  506. /// <param name="highByte"></param>
  507. /// <param name="intValue"></param>
  508. /// <returns></returns>
  509. public bool SendWriteRamIntValue(byte id,byte lowByte,byte highByte,int intValue)
  510. {
  511. if (_connected)
  512. {
  513. byte[] curveOffsetByte = BitConverter.GetBytes(intValue);
  514. byte[] byt = new byte[] { 0x01, id, 0x09, 0x02, 0x01, 0x03, lowByte, highByte, curveOffsetByte[0], curveOffsetByte[1], curveOffsetByte[2], curveOffsetByte[3],0x04 };
  515. _sendOperationQueue.Enqueue(byt);
  516. string str = string.Join(" ", Array.ConvertAll(byt, x => x.ToString("X2")));
  517. LOG.WriteBackgroundLog(eEvent.INFO_LINMOT, _name, $"Write Ram Int {str}");
  518. return true;
  519. }
  520. else
  521. {
  522. WriteErrorMsg($"{_name} is not connected");
  523. return false;
  524. }
  525. }
  526. /// <summary>
  527. /// 发送GAI GoToPosition指令
  528. /// </summary>
  529. /// <param name="id"></param>
  530. /// <param name="autoCount"></param>
  531. /// <param name="curveId"></param>
  532. /// <param name="timeScale"></param>
  533. /// <param name="curveOffset"></param>
  534. /// <param name="amplitudeScale"></param>
  535. public bool SendVAIGoToPositionOpertaion(byte id, int position,int velocity,int accel,int decel)
  536. {
  537. if (_connected)
  538. {
  539. //int positionValue = (int)Math.Round(position * 10000, 0);
  540. byte[] positionByt = BitConverter.GetBytes(position);
  541. //unit 0.1μm 1mm=1000μm
  542. //int velocityValue = (int)Math.Round(velocity * 1000);
  543. byte[] velocityByt = BitConverter.GetBytes(velocity);
  544. //accel--unit 0.1m/s^2
  545. //byte[] accelByt = BitConverter.GetBytes(accel * 1000);
  546. byte[] accelByt = BitConverter.GetBytes(accel);
  547. //decel--unit 0.1m/s^2
  548. //byte[] decelByte = BitConverter.GetBytes(decel * 1000);
  549. byte[] decelByte = BitConverter.GetBytes(decel);
  550. GenerateAutoCount();
  551. byte[] byt = new byte[] { 0x01, id, 0x15, 0x02, 0x00, 0x02, (byte)(0x00 | _autoCount), 0x01, positionByt[0], positionByt[1], positionByt[2], positionByt[3],
  552. velocityByt[0],velocityByt[1],velocityByt[2],velocityByt[3],accelByt[0],accelByt[1],accelByt[2],accelByt[3],
  553. decelByte[0],decelByte[1],decelByte[2],decelByte[3],0x04 };
  554. _sendOperationQueue.Enqueue(byt);
  555. return true;
  556. }
  557. else
  558. {
  559. WriteErrorMsg($"{_name} is not connected");
  560. return false;
  561. }
  562. }
  563. /// <summary>
  564. /// 发送GAI GoToPosition After Actual Position指令
  565. /// </summary>
  566. /// <param name="id"></param>
  567. /// <param name="autoCount"></param>
  568. /// <param name="curveId"></param>
  569. /// <param name="timeScale"></param>
  570. /// <param name="curveOffset"></param>
  571. /// <param name="amplitudeScale"></param>
  572. public bool SendVAIGoToPositionAfterAutalCommandOpertaion(byte id, int position, int velocity, int accel, int decel)
  573. {
  574. if (_connected)
  575. {
  576. //int positionValue = (int)Math.Round(position * 10000, 0);
  577. byte[] positionByt = BitConverter.GetBytes(position);
  578. //unit 0.1μm 1mm=1000μm
  579. //int velocityValue = (int)Math.Round(velocity * 1000);
  580. byte[] velocityByt = BitConverter.GetBytes(velocity);
  581. //accel--unit 0.1m/s^2
  582. //byte[] accelByt = BitConverter.GetBytes(accel * 1000);
  583. byte[] accelByt = BitConverter.GetBytes(accel);
  584. //decel--unit 0.1m/s^2
  585. //byte[] decelByte = BitConverter.GetBytes(decel * 1000);
  586. byte[] decelByte = BitConverter.GetBytes(decel);
  587. GenerateAutoCount();
  588. byte[] byt = new byte[] { 0x01, id, 0x15, 0x02, 0x00, 0x02, (byte)(0x80 | _autoCount), 0x01, positionByt[0], positionByt[1], positionByt[2], positionByt[3],
  589. velocityByt[0],velocityByt[1],velocityByt[2],velocityByt[3],accelByt[0],accelByt[1],accelByt[2],accelByt[3],
  590. decelByte[0],decelByte[1],decelByte[2],decelByte[3],0x04 };
  591. _sendOperationQueue.Enqueue(byt);
  592. return true;
  593. }
  594. else
  595. {
  596. WriteErrorMsg($"{_name} is not connected");
  597. return false;
  598. }
  599. }
  600. /// <summary>
  601. /// 创建操作指令
  602. /// </summary>
  603. /// <param name="id"></param>
  604. /// <param name="operation"></param>
  605. /// <returns></returns>
  606. private byte[] GenerateOperationBytes(byte id,LinMotOperation operation)
  607. {
  608. switch(operation)
  609. {
  610. case LinMotOperation.ReadStatus:
  611. return new byte[] { 0x01, id, 0x03, 0x02, 0x01, 0x00, 0x04 };
  612. case LinMotOperation.SwitchOn:
  613. return new byte[] { 0x01, id, 0x05, 0x02, 0x00, 0x01, 0x3F, 0x00, 0x04 };
  614. case LinMotOperation.SwitchOff:
  615. return new byte[] { 0x01, id, 0x05, 0x02, 0x00, 0x01, 0x3E, 0x00, 0x04 };
  616. case LinMotOperation.Home:
  617. return new byte[] { 0x01, id, 0x05, 0x02, 0x00, 0x01, 0x3F, 0x08, 0x04 };
  618. case LinMotOperation.ClearError:
  619. return new byte[] { 0x01, id, 0x05, 0x02, 0x00, 0x01, 0xBF, 0x00, 0x04 };
  620. case LinMotOperation.GoToInitialPosition:
  621. return new byte[]{ 0x01, id, 0x05, 0x02, 0x00, 0x01, 0x3F, 0x20, 0x04 };
  622. case LinMotOperation.ControlWordGoToPosition:
  623. return new byte[] { 0x01, id, 0x05, 0x02, 0x00, 0x01, 0x7F, 0x00, 0x04 };
  624. case LinMotOperation.Freeze:
  625. return new byte[] { 0x01, id, 0x05, 0x02, 0x00, 0x01, 0x1F, 0x00, 0x04 };
  626. default:
  627. return new byte[] { 0x01, id, 0x03, 0x02, 0x01, 0x00, 0x04 };
  628. }
  629. }
  630. /// <summary>
  631. /// 记录错误信息
  632. /// </summary>
  633. /// <param name="msg"></param>
  634. private void WriteErrorMsg(string msg, bool disConnected = true)
  635. {
  636. if (disConnected)
  637. {
  638. _connected = false;
  639. _offlineDateTime = DateTime.Now;
  640. }
  641. if (_errmsg != msg)
  642. {
  643. _errmsg = msg;
  644. LOG.WriteLog(eEvent.ERR_LINMOT, _name, msg);
  645. }
  646. }
  647. /// <summary>
  648. /// 写日志
  649. /// </summary>
  650. /// <param name="bytes"></param>
  651. private void WriteInfoMsg(int logType,byte[] bytes)
  652. {
  653. bool enableLog = false;
  654. if (SC.ContainsItem("Log.EnableLinmotLog"))
  655. {
  656. enableLog = SC.GetValue<bool>("Log.EnableLinmotLog");
  657. }
  658. if (enableLog)
  659. {
  660. string str = string.Join(" ", Array.ConvertAll(bytes, x => x.ToString("X2")));
  661. string type = logType == 0 ? "receive" : "send";
  662. LOG.WriteBackgroundLog(eEvent.INFO_LINMOT, _name, $"{type} {str}");
  663. }
  664. }
  665. /// <summary>
  666. /// 写日志
  667. /// </summary>
  668. /// <param name="bytes"></param>
  669. private void WriteInfoMsg(int logType, string str)
  670. {
  671. bool enableLog = false;
  672. if (SC.ContainsItem("Log.EnableLinmotLog"))
  673. {
  674. enableLog = SC.GetValue<bool>("Log.EnableLinmotLog");
  675. }
  676. if (enableLog)
  677. {
  678. string type = logType == 0 ? "receive" : "send";
  679. LOG.WriteBackgroundLog(eEvent.INFO_LINMOT, _name, $"{type} {str}");
  680. }
  681. }
  682. /// <summary>
  683. /// Curve每次数值得不同
  684. /// </summary>
  685. private void GenerateAutoCount()
  686. {
  687. lock (_autoCountLock)
  688. {
  689. _autoCount++;
  690. if (_autoCount >= 0x0D)
  691. {
  692. _autoCount = 1;
  693. }
  694. }
  695. }
  696. }
  697. }