MelsecA1EAsciiSocket.cs 16 KB

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