MelsecNetMultiAsync.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.Threading;
  8. using HslCommunication.Core;
  9. namespace HslCommunication.Profinet.Melsec
  10. {
  11. // internal sealed class MelsecNetMultiAsync : PlcNetBase
  12. // {
  13. // /// <summary>
  14. // /// 实例化一个多PLC请求的对象
  15. // /// </summary>
  16. // /// <param name="networkNumber">要求所有网络号一致</param>
  17. // /// <param name="networkStationNumber">要求所有站号一致</param>
  18. // /// <param name="type">要求所有读取类型一致</param>
  19. // /// <param name="address">要求所有起始地址一致</param>
  20. // /// <param name="length">要求所有读取数据长度一致</param>
  21. // /// <param name="timeout">连接PLC过程中的超时时间</param>
  22. // /// <param name="readCycle">每次请求访问的间隔时间</param>
  23. // /// <param name="allAddress">所有等待访问的PLC的IP地址</param>
  24. // /// <param name="portMain">访问PLC时的主端口</param>
  25. // /// <param name="portBackup">访问PLC时的备用端口</param>
  26. // public MelsecNetMultiAsync(
  27. // byte networkNumber,
  28. // byte networkStationNumber,
  29. // MelsecMcDataType type,
  30. // ushort address,
  31. // ushort length,
  32. // int timeout,
  33. // int readCycle,
  34. // IPAddress[] allAddress,
  35. // int portMain,
  36. // int portBackup )
  37. // {
  38. // NetworkNumber = networkNumber;
  39. // NetworkStationNumber = networkStationNumber;
  40. // MelsecType = type;
  41. // Address = address;
  42. // Length = length;
  43. // Timeout = timeout;
  44. // ReadCycle = readCycle;
  45. // //初始化数据对象
  46. // EveryMachineLength = GetLengthFromPlcType( type, length );
  47. // BytesResult = new byte[EveryMachineLength * allAddress.Length];
  48. // PlcStates = new PlcStateOne[allAddress.Length];
  49. // for (int i = 0; i < PlcStates.Length; i++)
  50. // {
  51. // PlcStates[i] = new PlcStateOne( )
  52. // {
  53. // Index = i,
  54. // PlcDataHead = new byte[9],
  55. // PlcDataContent = new byte[EveryMachineLength],
  56. // LengthDataContent = 0,
  57. // LengthDataHead = 0,
  58. // IsConnect = false,
  59. // PlcIpAddress = allAddress[i],
  60. // PortMain = portMain,
  61. // PortBackup = portBackup,
  62. // };
  63. // }
  64. // //启动线程
  65. // Thread thread = new Thread( new ThreadStart( ThreadDealWithTimeout ) )
  66. // {
  67. // IsBackground = true
  68. // };
  69. // thread.Start( );
  70. // }
  71. // /*********************************************************************************************
  72. // *
  73. // * 拷贝的数据方式仍然需要修改
  74. // *
  75. // *
  76. // *********************************************************************************************/
  77. // private MelsecMcDataType MelsecType = MelsecMcDataType.D;
  78. // private ushort Address = 0;
  79. // private ushort Length = 0;
  80. // /// <summary>
  81. // /// 超时时间
  82. // /// </summary>
  83. // private int Timeout = 600;
  84. // /// <summary>
  85. // /// 访问周期
  86. // /// </summary>
  87. // private int ReadCycle = 1000;
  88. // /// <summary>
  89. // /// 系统的连接状态,0未连接,1连接中
  90. // /// </summary>
  91. // private int ConnectStatus = 0;
  92. // /// <summary>
  93. // /// 用于存储结果的字节数组
  94. // /// </summary>
  95. // private byte[] BytesResult = null;
  96. // /// <summary>
  97. // /// 每台设备的长度
  98. // /// </summary>
  99. // private int EveryMachineLength = 0;
  100. // /// <summary>
  101. // /// 接收到所有的PLC数据时候触发
  102. // /// </summary>
  103. // public event IEDelegate<byte[]> OnReceivedData = null;
  104. // private PlcStateOne[] PlcStates = null;
  105. // /// <summary>
  106. // /// 维护超时连接的线程方法
  107. // /// </summary>
  108. // private void ThreadDealWithTimeout()
  109. // {
  110. // LogNet?.WriteInfo( LogHeaderText, "waitting one second" );
  111. // Thread.Sleep( 1000 );// 刚启动的时候进行休眠一小会
  112. // LogNet?.WriteInfo( LogHeaderText, "begining recyle for reading plc" );
  113. // while (true)
  114. // {
  115. // DateTime firstTime = DateTime.Now;// 连接时间
  116. // TimerCallBack( );// 启动访问PLC
  117. // while ((DateTime.Now - firstTime).TotalMilliseconds < Timeout)
  118. // {
  119. // // 超时时间等待
  120. // }
  121. // // 连接超时处理
  122. // for (int i = 0; i < PlcStates.Length; i++)
  123. // {
  124. // if (!PlcStates[i].IsConnect) PlcStates[i].WorkSocket.Close( );
  125. // }
  126. // while ((DateTime.Now - firstTime).TotalMilliseconds < ReadCycle)
  127. // {
  128. // // 等待下次连接
  129. // }
  130. // }
  131. // }
  132. // private void TimerCallBack()
  133. // {
  134. // // 如果已经连接就返回,此处采用原子操作实现
  135. // if (Interlocked.CompareExchange( ref ConnectStatus, 1, 0 ) == 0)
  136. // {
  137. // m_ac = new AsyncCoordinator( );
  138. // for (int i = 0; i < PlcStates.Length; i++)
  139. // {
  140. // PlcStates[i].IsConnect = false;
  141. // PlcStates[i].WorkSocket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
  142. // PlcStates[i].WorkSocket.BeginConnect( new IPEndPoint( PlcStates[i].PlcIpAddress, PlcStates[i].GetPort( ) ), new AsyncCallback( PlcConnectCallBack ), PlcStates[i] );
  143. // PlcStates[i].LengthDataHead = 0;
  144. // PlcStates[i].LengthDataContent = 0;
  145. // m_ac.AboutToBegin( 1 );
  146. // }
  147. // // 启动检查连接情况
  148. // m_ac.AllBegun( AllDown );
  149. // }
  150. // }
  151. // private byte[] ConnectWrongHead = new byte[] { 0x00, 0x01 };
  152. // private void PlcConnectCallBack( IAsyncResult ar )
  153. // {
  154. // if (ar.AsyncState is PlcStateOne stateone)
  155. // {
  156. // try
  157. // {
  158. // stateone.WorkSocket.EndConnect( ar );
  159. // stateone.WorkSocket.BeginReceive(
  160. // stateone.PlcDataHead,
  161. // stateone.LengthDataHead,
  162. // stateone.PlcDataHead.Length - stateone.LengthDataHead,
  163. // SocketFlags.None,
  164. // new AsyncCallback( PlcHeadReceiveCallBack ),
  165. // stateone );
  166. // stateone.IsConnect = true;// 指示访问成功
  167. // }
  168. // catch (Exception ex)
  169. // {
  170. // LogNet?.WriteException( ToString(), "connect failed", ex );
  171. // // 访问失败
  172. // stateone.WorkSocket.Close( );
  173. // // 初始化数据
  174. // Array.Copy( ConnectWrongHead, 0, BytesResult, stateone.Index * EveryMachineLength, 2 );
  175. // // 更换端口
  176. // stateone.ChangePort( );
  177. // // 结束任务
  178. // m_ac.JustEnded( );
  179. // }
  180. // }
  181. // }
  182. // private void PlcHeadReceiveCallBack( IAsyncResult ar )
  183. // {
  184. // if (ar.AsyncState is PlcStateOne stateone)
  185. // {
  186. // try
  187. // {
  188. // stateone.LengthDataHead += stateone.WorkSocket.EndReceive( ar );
  189. // if (stateone.LengthDataHead < stateone.PlcDataHead.Length)
  190. // {
  191. // // 继续接收头格式
  192. // stateone.WorkSocket.BeginReceive(
  193. // stateone.PlcDataHead,
  194. // stateone.LengthDataHead,
  195. // stateone.PlcDataHead.Length - stateone.LengthDataHead,
  196. // SocketFlags.None,
  197. // new AsyncCallback( PlcHeadReceiveCallBack ),
  198. // stateone );
  199. // }
  200. // else
  201. // {
  202. // // 计算接下来的接收长度,最少还有2个长度的字节数据
  203. // int NeedReceived = BitConverter.ToUInt16( stateone.PlcDataHead, 7 );
  204. // stateone.PlcDataContent = new byte[NeedReceived];
  205. // // 接收内容
  206. // stateone.WorkSocket.BeginReceive(
  207. // stateone.PlcDataContent,
  208. // 0,
  209. // stateone.PlcDataContent.Length - stateone.LengthDataContent,
  210. // SocketFlags.None,
  211. // new AsyncCallback( PlcContentReceiveCallBack ),
  212. // stateone );
  213. // }
  214. // }
  215. // catch (Exception ex)
  216. // {
  217. // LogNet?.WriteException( LogHeaderText, "Head receive", ex );
  218. // // 由于未知原因,数据接收失败
  219. // stateone.WorkSocket.Close( );
  220. // // 初始化数据
  221. // Array.Copy( ConnectWrongHead, 0, BytesResult, stateone.Index * EveryMachineLength, 2 );
  222. // // 结束任务
  223. // m_ac.JustEnded( );
  224. // }
  225. // }
  226. // }
  227. // private void PlcContentReceiveCallBack( IAsyncResult ar )
  228. // {
  229. // if (ar.AsyncState is PlcStateOne stateone)
  230. // {
  231. // try
  232. // {
  233. // stateone.LengthDataContent += stateone.WorkSocket.EndReceive( ar );
  234. // if (stateone.LengthDataHead < stateone.PlcDataHead.Length)
  235. // {
  236. // // 继续接内容格式
  237. // stateone.WorkSocket.BeginReceive(
  238. // stateone.PlcDataContent,
  239. // stateone.LengthDataContent,
  240. // stateone.PlcDataContent.Length - stateone.LengthDataContent,
  241. // SocketFlags.None,
  242. // new AsyncCallback( PlcContentReceiveCallBack ),
  243. // stateone );
  244. // }
  245. // else
  246. // {
  247. // // 所有内容接收完成
  248. // int error = BitConverter.ToUInt16( stateone.PlcDataContent, 0 );
  249. // if (error > 0)
  250. // {
  251. // Array.Copy( ConnectWrongHead, 0, BytesResult, stateone.Index * EveryMachineLength, 2 );
  252. // }
  253. // else
  254. // {
  255. // Array.Copy( stateone.PlcDataContent, 0, BytesResult, stateone.Index * EveryMachineLength, stateone.PlcDataContent.Length );
  256. // }
  257. // // 关闭连接
  258. // stateone.WorkSocket.Close( );
  259. // // 结束任务
  260. // m_ac.JustEnded( );
  261. // }
  262. // }
  263. // catch (Exception ex)
  264. // {
  265. // LogNet?.WriteException( LogHeaderText, "Data receive", ex );
  266. // // 由于未知原因,数据接收失败
  267. // stateone.WorkSocket.Close( );
  268. // // 初始化数据
  269. // Array.Copy( ConnectWrongHead, 0, BytesResult, stateone.Index * EveryMachineLength, 2 );
  270. // // 结束任务
  271. // m_ac.JustEnded( );
  272. // }
  273. // }
  274. // }
  275. // private void AllDown( CoordinationStatus status )
  276. // {
  277. // // 此处没有取消和超时状态,直接完成
  278. // if (status == CoordinationStatus.AllDone)
  279. // {
  280. // Interlocked.Exchange( ref ConnectStatus, 0 );
  281. // LogNet?.WriteDebug( LogHeaderText, "All bytes read complete." );
  282. // OnReceivedData?.Invoke( BytesResult.ToArray( ) );
  283. // }
  284. // }
  285. // private AsyncCoordinator m_ac = new AsyncCoordinator( );
  286. // }
  287. }