MelsecA1EAscii.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using Dongke.IBOSS.PRD.Basics.Library;
  6. using HslCommunication;
  7. using HslCommunication.Profinet.Melsec;
  8. namespace PCLCommunication
  9. {
  10. /// <summary>
  11. /// 三菱 A 1E Ascii
  12. /// </summary>
  13. public class MelsecA1EAscii : IDisposable
  14. {
  15. private bool _always = false;
  16. [NonSerialized]
  17. private Socket _socket = null;
  18. //[NonSerialized]
  19. private StringBuilder _command = null;
  20. //[NonSerialized]
  21. private string _receive = null;
  22. [NonSerialized]
  23. private MelsecA1EAsciiNet _MelsecA1EAsciiNet = null;
  24. /// <summary>
  25. /// 传输的命令
  26. /// </summary>
  27. public string Command
  28. {
  29. get
  30. {
  31. return this._command?.ToString();
  32. }
  33. }
  34. /// <summary>
  35. /// 命令结果
  36. /// </summary>
  37. public string Receive
  38. {
  39. get
  40. {
  41. return this._receive;
  42. }
  43. }
  44. /// <summary>
  45. /// 是:长连接;否:短连接
  46. /// </summary>
  47. public bool Always
  48. {
  49. get
  50. {
  51. return this._always;
  52. }
  53. set
  54. {
  55. this._always = value;
  56. if (!this._always)
  57. {
  58. this.CloseSocket();
  59. }
  60. else
  61. {
  62. this.ConnectSocket();
  63. }
  64. }
  65. }
  66. ///// <summary>
  67. ///// Socket
  68. ///// </summary>
  69. //[System.Xml.Serialization.XmlIgnore]
  70. //[System.Web.Script.Serialization.ScriptIgnore]
  71. //public Socket Socket
  72. //{
  73. // get
  74. // {
  75. // return this._socket;
  76. // }
  77. //}
  78. /// <summary>
  79. /// 通信超时(3s)
  80. /// </summary>
  81. public int Timeout
  82. {
  83. get;
  84. set;
  85. } = 10000;//3000;
  86. /// <summary>
  87. /// 关闭连接
  88. /// </summary>
  89. public void CloseSocket()
  90. {
  91. try
  92. {
  93. //_socket?.Close();
  94. this._MelsecA1EAsciiNet?.ConnectClose();
  95. }
  96. catch (Exception ex)
  97. {
  98. // TODO log
  99. string j = JsonHelper.ToJson(this);
  100. LogOut.Error(null, ex, j);
  101. //throw ex;
  102. }
  103. finally
  104. {
  105. //_socket = null;
  106. //this._MelsecA1EAsciiNet = null;
  107. }
  108. }
  109. /// <summary>
  110. /// 打开连接
  111. /// </summary>
  112. public void ConnectSocket()
  113. {
  114. try
  115. {
  116. //_socket?.Close();
  117. //this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  118. //this._socket.Connect(IPAddress.Parse(this.IP), this.Port);
  119. //this._socket.SendTimeout = this.Timeout;
  120. //this._socket.ReceiveTimeout = this.Timeout;
  121. this._MelsecA1EAsciiNet?.ConnectClose();
  122. if (this._MelsecA1EAsciiNet == null)
  123. {
  124. this._MelsecA1EAsciiNet = new MelsecA1EAsciiNet(this.IP, this.Port);
  125. }
  126. this._MelsecA1EAsciiNet.ConnectTimeOut = this.Timeout;
  127. this._MelsecA1EAsciiNet.ReceiveTimeOut = this.Timeout;
  128. this._MelsecA1EAsciiNet.ConnectServer();
  129. }
  130. catch (Exception ex)
  131. {
  132. // TODO log
  133. throw ex;
  134. }
  135. finally
  136. {
  137. if (!this._always)
  138. {
  139. CloseSocket();
  140. }
  141. }
  142. }
  143. /// <summary>
  144. /// PLC IP
  145. /// </summary>
  146. public string IP
  147. {
  148. get
  149. {
  150. return this._MelsecA1EAsciiNet.IpAddress;
  151. }
  152. set
  153. {
  154. this._MelsecA1EAsciiNet.IpAddress = value;
  155. }
  156. }
  157. /// <summary>
  158. /// PLC Port
  159. /// </summary>
  160. public int Port
  161. {
  162. get
  163. {
  164. return this._MelsecA1EAsciiNet.Port;
  165. }
  166. set
  167. {
  168. this._MelsecA1EAsciiNet.Port = value;
  169. }
  170. }
  171. public MelsecA1EAscii(string ip, int port)
  172. {
  173. _MelsecA1EAsciiNet = new MelsecA1EAsciiNet(ip, port);
  174. this._MelsecA1EAsciiNet.ConnectTimeOut = this.Timeout;
  175. this._MelsecA1EAsciiNet.ReceiveTimeOut = this.Timeout;
  176. //this.IP = ip;
  177. //this.Port = port;
  178. }
  179. /// <summary>
  180. /// 读取PLC
  181. /// </summary>
  182. /// <param name="type"></param>
  183. /// <param name="begin"></param>
  184. /// <param name="length"></param>
  185. /// <returns></returns>
  186. public string GetHexData(string type, int begin, int length)
  187. {
  188. this._command = null;
  189. this._receive = null;
  190. string mm = "\r\ntype:" + type + "\r\nbegin:" + begin + "\r\nlength:" + length;
  191. try
  192. {
  193. //if (this._socket == null || !this._always)
  194. //{
  195. // this.CloseSocket();
  196. // this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  197. // this._socket.Connect(IPAddress.Parse(this.IP), this.Port);
  198. // this._socket.SendTimeout = this.Timeout;
  199. // this._socket.ReceiveTimeout = this.Timeout;
  200. //}
  201. // 副标题: 01 【命令:字单位读取】
  202. // PC号: FF 【固定】
  203. // 监视定时器:00 0C 【3秒(单位250毫秒)】
  204. this._command = new StringBuilder("01FF000C");
  205. // 起始软元件编码 D100 => 4420 0000 0064
  206. // 软元件代码
  207. if (type.Length == 1)
  208. {
  209. this._command.Append(MelsecA1EAscii.GetHexAscii(type) + "20");
  210. }
  211. else
  212. {
  213. this._command.Append(MelsecA1EAscii.GetHexAscii(type));
  214. }
  215. // 软元件编码
  216. this._command.Append(begin.ToString("X8"));
  217. // 软元件点数
  218. this._command.Append(length.ToString("X2"));
  219. // 命令结束
  220. this._command.Append("00");
  221. byte[] cmdBytes = Encoding.ASCII.GetBytes(this._command.ToString());
  222. //int cmdResult = this._socket.Send(cmdBytes);
  223. //byte[] receiveBytes = new byte[length * 4 + 4];
  224. //int receiveResult = this._socket.Receive(receiveBytes);
  225. //this._receive = Encoding.ASCII.GetString(receiveBytes, 0, receiveResult);
  226. //if (!this._receive.StartsWith("8100"))
  227. //{
  228. // // TODO log ip port command receive
  229. // string j = JsonHelperForPC.ToJson(this) + mm;
  230. // LogOut.Error(null, null, j);
  231. // return null;
  232. //}
  233. OperateResult<byte[]> result = this._MelsecA1EAsciiNet.ReadFromCoreServer(cmdBytes);
  234. if (result.IsSuccess)
  235. {
  236. this._receive = Encoding.ASCII.GetString(result.Content);
  237. if (!this._receive.StartsWith("8100"))
  238. {
  239. // TODO log ip port command receive
  240. string j = JsonHelper.ToJson(this) + mm;
  241. LogOut.Error(null, null, j);
  242. return null;
  243. }
  244. }
  245. else
  246. {
  247. // TODO log ip port command receive
  248. string j = JsonHelper.ToJson(this) + mm + "\r\nError:" + result.ToMessageShowString();
  249. LogOut.Error(null, null, j);
  250. return null;
  251. }
  252. //return receive.Substring(4);
  253. return this._receive;
  254. }
  255. catch (Exception ex)
  256. {
  257. // TODO log
  258. string j = JsonHelper.ToJson(this) + mm;
  259. LogOut.Error(null, ex, j);
  260. return null;
  261. }
  262. finally
  263. {
  264. if (!this._always)
  265. {
  266. this.CloseSocket();
  267. }
  268. }
  269. }
  270. /// <summary>
  271. /// 读取PLC
  272. /// </summary>
  273. /// <param name="type"></param>
  274. /// <param name="begin"></param>
  275. /// <param name="length"></param>
  276. /// <returns></returns>
  277. public byte[] GetByteData(string type, int begin, int length)
  278. {
  279. string mm = "\r\ntype:" + type + "\r\nbegin:" + begin + "\r\nlength:" + length;
  280. try
  281. {
  282. string str = this.GetHexData(type, begin, length);
  283. if (string.IsNullOrEmpty(str))
  284. {
  285. return null;
  286. }
  287. List<byte> list = new List<byte>();
  288. for (int i = 4; i < str.Length; i = i + 2)
  289. {
  290. list.Add(Convert.ToByte(str.Substring(i, 2), 16));
  291. }
  292. return list.ToArray();
  293. }
  294. catch (Exception ex)
  295. {
  296. // TODO log
  297. string j = JsonHelper.ToJson(this) + mm;
  298. LogOut.Error(null, ex, j);
  299. return null;
  300. }
  301. finally
  302. {
  303. }
  304. }
  305. /// <summary>
  306. /// 写入PLC
  307. /// </summary>
  308. /// <param name="type"></param>
  309. /// <param name="begin"></param>
  310. /// <param name="length"></param>
  311. /// <returns></returns>
  312. public bool SetData(string type, int begin, int length, string hexData)
  313. {
  314. this._command = null;
  315. this._receive = null;
  316. string mm = "\r\ntype:" + type + "\r\nbegin:" + begin + "\r\nlength:" + length + "\r\nhexData:" + hexData;
  317. try
  318. {
  319. //if (this._socket == null || !this._always)
  320. //{
  321. // this.CloseSocket();
  322. // this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  323. // this._socket.Connect(IPAddress.Parse(this.IP), this.Port);
  324. // this._socket.SendTimeout = this.Timeout;
  325. // this._socket.ReceiveTimeout = this.Timeout;
  326. //}
  327. // 副标题: 03 【命令:字单位写入】
  328. // PC号: FF 【固定】
  329. // 监视定时器:00 0C 【3秒(单位250毫秒)】
  330. this._command = new StringBuilder("03FF000C");
  331. // 起始软元件编码 D100 => 4420 0000 0064
  332. // 软元件代码
  333. if (type.Length == 1)
  334. {
  335. this._command.Append(MelsecA1EAscii.GetHexAscii(type) + "20");
  336. }
  337. else
  338. {
  339. this._command.Append(MelsecA1EAscii.GetHexAscii(type));
  340. }
  341. // 软元件编码
  342. this._command.Append(begin.ToString("X8"));
  343. // 软元件点数
  344. this._command.Append(length.ToString("X2"));
  345. // 命令结束
  346. this._command.Append("00");
  347. // 写入补齐
  348. int count = length * 4;
  349. if (hexData.Length < count)
  350. {
  351. hexData = hexData.PadRight(count, '0');
  352. }
  353. //if (hexData.Length > count)
  354. //{
  355. // hexData = hexData.Substring(0, count);
  356. //}
  357. // 写入
  358. this._command.Append(hexData);
  359. byte[] cmdBytes = Encoding.ASCII.GetBytes(this._command.ToString());
  360. //int cmdResult = this._socket.Send(cmdBytes);
  361. //byte[] receiveBytes = new byte[1024];
  362. //int receiveResult = this._socket.Receive(receiveBytes);
  363. //this._receive = Encoding.ASCII.GetString(receiveBytes, 0, receiveResult);
  364. //if (!this._receive.StartsWith("8300"))
  365. //{
  366. // // TODO log ip port command receive
  367. // string j = JsonHelperForPC.ToJson(this) + mm;
  368. // LogOut.Error(null, null, j);
  369. // return false;
  370. //}
  371. OperateResult<byte[]> result = this._MelsecA1EAsciiNet.ReadFromCoreServer(cmdBytes);
  372. if (result.IsSuccess)
  373. {
  374. this._receive = Encoding.ASCII.GetString(result.Content);
  375. if (!this._receive.StartsWith("8300"))
  376. {
  377. // TODO log ip port command receive
  378. string j = JsonHelper.ToJson(this) + mm;
  379. LogOut.Error(null, null, j);
  380. return false;
  381. }
  382. }
  383. else
  384. {
  385. // TODO log ip port command receive
  386. string j = JsonHelper.ToJson(this) + mm + "\r\nError:" + result.ToMessageShowString();
  387. LogOut.Error(null, null, j);
  388. return false;
  389. }
  390. return true;
  391. }
  392. catch (Exception ex)
  393. {
  394. // TODO log
  395. string j = JsonHelper.ToJson(this) + mm;
  396. LogOut.Error(null, ex, j);
  397. return false;
  398. }
  399. finally
  400. {
  401. if (!this._always)
  402. {
  403. this.CloseSocket();
  404. }
  405. }
  406. }
  407. /// <summary>
  408. /// 写入PLC
  409. /// </summary>
  410. /// <param name="type"></param>
  411. /// <param name="begin"></param>
  412. /// <param name="hexData"></param>
  413. /// <returns></returns>
  414. public bool SetData(string type, int begin, string hexData)
  415. {
  416. int length = (int)(hexData.Length / 4.0 + 0.5);
  417. return this.SetData(type, begin, length, hexData);
  418. }
  419. /// <summary>
  420. /// 写入PLC
  421. /// </summary>
  422. /// <param name="type"></param>
  423. /// <param name="begin"></param>
  424. /// <returns></returns>
  425. public bool SetData(string type, int begin, byte[] data)
  426. {
  427. try
  428. {
  429. StringBuilder sb = new StringBuilder();
  430. foreach (byte item in data)
  431. {
  432. sb.Append(item.ToString("X2"));
  433. }
  434. return SetData(type, begin, sb.ToString());
  435. }
  436. catch (Exception ex)
  437. {
  438. // TODO log
  439. LogOut.Error(null, ex);
  440. return false;
  441. }
  442. finally
  443. {
  444. }
  445. }
  446. /// <summary>
  447. /// 写入PLC
  448. /// </summary>
  449. /// <param name="type"></param>
  450. /// <param name="begin"></param>
  451. /// <param name="length"></param>
  452. /// <returns></returns>
  453. public bool SetData(string type, int begin, int length, byte[] data)
  454. {
  455. try
  456. {
  457. StringBuilder sb = new StringBuilder();
  458. foreach (byte item in data)
  459. {
  460. sb.Append(item.ToString("X2"));
  461. }
  462. return SetData(type, begin, length, sb.ToString());
  463. }
  464. catch (Exception ex)
  465. {
  466. // TODO log
  467. LogOut.Error(null, ex);
  468. return false;
  469. }
  470. finally
  471. {
  472. if (!this._always)
  473. {
  474. this.CloseSocket();
  475. }
  476. }
  477. }
  478. public void Do(string command)
  479. {
  480. this._command = null;
  481. this._receive = null;
  482. try
  483. {
  484. //if (this._socket == null || !this._always)
  485. //{
  486. // this.CloseSocket();
  487. // this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  488. // this._socket.Connect(IPAddress.Parse(this.IP), this.Port);
  489. // this._socket.SendTimeout = this.Timeout;
  490. // this._socket.ReceiveTimeout = this.Timeout;
  491. //}
  492. this._command = new StringBuilder(command);
  493. byte[] cmdBytes = Encoding.ASCII.GetBytes(command);
  494. //int cmdResult = this._socket.Send(cmdBytes);
  495. //byte[] receiveBytes = new byte[4096];
  496. //int receiveResult = this._socket.Receive(receiveBytes);
  497. //this._receive = Encoding.ASCII.GetString(receiveBytes, 0, receiveResult);
  498. OperateResult<byte[]> result = this._MelsecA1EAsciiNet.ReadFromCoreServer(cmdBytes);
  499. if (result.IsSuccess)
  500. {
  501. this._receive = Encoding.ASCII.GetString(result.Content);
  502. }
  503. else
  504. {
  505. // TODO log ip port command receive
  506. string j = JsonHelper.ToJson(this) + "\r\nError:" + result.ToMessageShowString();
  507. LogOut.Error(null, null, j);
  508. }
  509. }
  510. catch (Exception ex)
  511. {
  512. // TODO log
  513. string j = JsonHelper.ToJson(this);
  514. LogOut.Error(null, ex, j);
  515. }
  516. finally
  517. {
  518. if (!this._always)
  519. {
  520. this.CloseSocket();
  521. }
  522. }
  523. }
  524. /// <summary>
  525. /// 获取字符串对应的2进制Ascii码(字符=>命令)
  526. /// </summary>
  527. /// <param name="value"></param>
  528. /// <returns></returns>
  529. public static string GetHexAscii(string value)
  530. {
  531. if (string.IsNullOrEmpty(value))
  532. {
  533. return "";
  534. }
  535. byte[] bs = Encoding.ASCII.GetBytes(value);
  536. if (bs.Length > 1)
  537. {
  538. StringBuilder sb = new StringBuilder();
  539. foreach (byte item in bs)
  540. {
  541. sb.Append(item.ToString("X2"));
  542. }
  543. return sb.ToString();
  544. }
  545. else
  546. {
  547. return bs[0].ToString("X2");
  548. }
  549. }
  550. /// <summary>
  551. /// 获取2进制Ascii码对应的字符串(命令=>字符)
  552. /// </summary>
  553. /// <param name="value"></param>
  554. /// <returns></returns>
  555. public static string GetByHexAscii(string value)
  556. {
  557. if (string.IsNullOrWhiteSpace(value))
  558. {
  559. return null;
  560. }
  561. List<byte> list = new List<byte>();
  562. for (int i = 0; i < value.Length; i = i + 2)
  563. {
  564. list.Add(Convert.ToByte(value.Substring(i, 2), 16));
  565. }
  566. return Encoding.ASCII.GetString(list.ToArray());
  567. }
  568. /// <summary>
  569. /// 销毁
  570. /// </summary>
  571. public void Dispose()
  572. {
  573. try
  574. {
  575. this.CloseSocket();
  576. }
  577. catch
  578. {
  579. }
  580. }
  581. }
  582. }