MCProtocolPlcSimulator.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.Sockets;
  9. using System.Runtime.InteropServices;
  10. using System.Text;
  11. using System.Text.RegularExpressions;
  12. using System.Threading;
  13. using System.Threading.Tasks;
  14. using System.Windows;
  15. using Aitex.Core.RT.Log;
  16. using Aitex.Core.Util;
  17. using MECF.Framework.RT.Core.IoProviders;
  18. namespace MECF.Framework.Simulator.Core.IoProviders
  19. {
  20. public class PlcBuffer
  21. {
  22. public IoType Type;
  23. public int Offset;
  24. public int Size;
  25. public byte[] Buffer;
  26. public bool[] BoolValue;
  27. public ushort[] ShortValue;
  28. public float[] FloatValue;
  29. }
  30. public class MCProtocolPlcSimulator
  31. {
  32. public event Action<string> NotifyEvent;
  33. private PeriodicJob _threadSocket;
  34. private PeriodicJob _threadTimer;
  35. private Socket _socketServer;
  36. private string _ip;
  37. private bool _stopFlag;
  38. protected List<PlcBuffer> _buffers = new List<PlcBuffer>();
  39. private int _port = 6731;
  40. private int _socketId = 101;
  41. private int _stationId = 102;
  42. private byte[] _bufferIn;
  43. private byte[] _bufferOut;
  44. private MCProtocol.MC_RESPONSE_HEADER _response;
  45. public MCProtocolPlcSimulator(string ip, int port)
  46. {
  47. _ip = ip;
  48. _port = port;
  49. _response = new MCProtocol.MC_RESPONSE_HEADER()
  50. {
  51. ProtocolId = MCProtocol.MC_SUBHEADER_RESPONSE_MESSAGE,
  52. NetworkId = (byte)_socketId,
  53. StationId = (byte)_stationId,
  54. RequestIoNumber = MCProtocol.MC_REQUEST_MODULE_IO_NUMBER,
  55. RequestStationNumber = MCProtocol.MC_REQUEST_MODULE_STATION_NUMBER,
  56. ResponseDataLen = 0,
  57. CompleteCode = (ushort)(MCProtocol.MC_COMPLETE_CODE_SUCCESS ),
  58. };
  59. _bufferOut = new byte[2048];
  60. _bufferIn = new byte[2048];
  61. _socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  62. _threadSocket = new PeriodicJob(50, OnMonitor, "MCProtocolPlcSimulator",true);
  63. _threadTimer = new PeriodicJob(1000, OnTimer, "MCProtocolPlcSimulatorTimer", true);
  64. }
  65. protected virtual bool OnTimer()
  66. {
  67. return true;
  68. }
  69. private void PerformNotifyEvent(string msg)
  70. {
  71. if (NotifyEvent != null)
  72. {
  73. NotifyEvent(msg);
  74. }
  75. }
  76. private bool OnMonitor()
  77. {
  78. try
  79. {
  80. EndPoint ep = new IPEndPoint(IPAddress.Loopback, _port);
  81. _socketServer.Bind(ep);
  82. _socketServer.Listen(3);
  83. Socket s;
  84. while (!_stopFlag)
  85. {
  86. PerformNotifyEvent("Waiting for connection ...");
  87. s = _socketServer.Accept();
  88. PerformNotifyEvent("Connected.");
  89. s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
  90. try
  91. {
  92. while (!_stopFlag && OnTransmission(s))
  93. {
  94. PerformNotifyEvent("Waiting for another command ...");
  95. }
  96. PerformNotifyEvent("receive error buffer content and exit ...");
  97. }
  98. catch (Exception ex)
  99. {
  100. LOG.Write(ex);
  101. return true;
  102. }
  103. PerformNotifyEvent("A client disconnected from port " + _port);
  104. s = null;
  105. }
  106. }
  107. catch (Exception ex)
  108. {
  109. LOG.Write(ex);
  110. try
  111. {
  112. _socketServer.Close();
  113. }
  114. catch (Exception )
  115. {
  116. }
  117. _socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  118. return true;
  119. }
  120. return true;
  121. }
  122. public void Start()
  123. {
  124. _threadSocket.Start();
  125. }
  126. public void Stop()
  127. {
  128. _stopFlag = true;
  129. _threadSocket.Stop();
  130. }
  131. protected bool OnTransmission(Socket s)
  132. {
  133. int size = s.Receive(_bufferIn, 0, MCProtocol.MC_QHEADER_COMMAND_SIZE, SocketFlags.None);
  134. if (size < MCProtocol.MC_QHEADER_COMMAND_SIZE)
  135. {
  136. return false;
  137. }
  138. MCProtocol.MC_COMMAND_HEADER header = MCProtocol.ToStruct<MCProtocol.MC_COMMAND_HEADER>(_bufferIn);
  139. int dataLength = header.RequestDataLen - MCProtocol.MC_BATCH_COMMAND_SIZE - MCProtocol.JUNK_SIZE;
  140. if (dataLength < 0)
  141. {
  142. return false;
  143. }
  144. size = s.Receive(_bufferIn, 0, MCProtocol.MC_BATCH_COMMAND_SIZE, SocketFlags.None);
  145. if (size < MCProtocol.MC_BATCH_COMMAND_SIZE)
  146. {
  147. return false;
  148. }
  149. MCProtocol.MC_BATCH_COMMAND cmd = MCProtocol.ToStruct<MCProtocol.MC_BATCH_COMMAND>(_bufferIn);
  150. int offset = cmd.Reserved * (0xFFFF + 1) + cmd.HeadAddr;
  151. if (dataLength > 0)
  152. {
  153. size = s.Receive(_bufferIn, 0, dataLength, SocketFlags.None);
  154. if (size < dataLength)
  155. {
  156. return false;
  157. }
  158. }
  159. byte[] data = null;
  160. if (cmd.Command == MCProtocol.MC_COMMAND_BATCH_READ)
  161. {
  162. data = GetData(offset, cmd.DevicePoints, cmd.SubCommand == MCProtocol.MC_SUBCOMMAND_BIT_UNITS);
  163. }
  164. else
  165. {
  166. SetData(offset, _bufferIn, dataLength, cmd.SubCommand == MCProtocol.MC_SUBCOMMAND_BIT_UNITS);
  167. }
  168. _response.ResponseDataLen = (ushort)(MCProtocol.JUNK_SIZE + (data == null ? 0 : data.Length));
  169. byte[] response = MCProtocol.Struct2Bytes(_response);
  170. Array.Copy(response, 0, _bufferOut, 0, response.Length);
  171. s.Send(_bufferOut, response.Length, SocketFlags.None);
  172. if (data != null)
  173. {
  174. Array.Copy(data, 0, _bufferOut, 0, data.Length);
  175. s.Send(_bufferOut, data.Length, SocketFlags.None);
  176. }
  177. return true;
  178. }
  179. protected void SetData(int headAddr, byte[] data, int length, bool isBit)
  180. {
  181. IoType ioType = isBit ? IoType.DO : IoType.AO;
  182. if (ioType == IoType.DO)
  183. {
  184. bool[] boolData = MCProtocol.TransByteDataToBoolArray(data, 0, length);
  185. PlcBuffer buffer = _buffers.Find(x => x.Offset == headAddr && x.Type == ioType && x.Size == boolData.Length);
  186. if (buffer != null)
  187. {
  188. buffer.BoolValue = boolData;
  189. }
  190. }
  191. else
  192. {
  193. ushort[] shortValue = MCProtocol.Byte2Ushort(data, 0, length);
  194. PlcBuffer buffer = _buffers.Find(x=>x.Type == ioType);
  195. if (buffer != null && shortValue != null && shortValue.Length > 0 && buffer.ShortValue.Length >= headAddr + shortValue.Length)
  196. {
  197. Array.Copy(shortValue, 0, buffer.ShortValue, headAddr, shortValue.Length);
  198. }
  199. }
  200. }
  201. protected void SetDi(int headAddr, int offset, bool value)
  202. {
  203. PlcBuffer buffer = _buffers.Find(x =>x.Type == IoType.DI );
  204. if (buffer != null)
  205. {
  206. buffer.BoolValue[offset] = value;
  207. }
  208. }
  209. protected void SetAi(int headAddr, int offset, ushort value)
  210. {
  211. PlcBuffer buffer = _buffers.Find(x => x.Type == IoType.AI );
  212. if (buffer != null)
  213. {
  214. buffer.ShortValue[offset] = value;
  215. }
  216. }
  217. protected virtual byte[] GetData(int headAddr, ushort length, bool isBit)
  218. {
  219. IoType ioType = isBit ? IoType.DI : IoType.AI;
  220. if(!isBit)
  221. {
  222. var tmp = _buffers.Find(x => x.Type == ioType);
  223. if(tmp != null && tmp.ShortValue != null)
  224. {
  225. var remain = tmp.ShortValue.Length - headAddr;
  226. var size = remain >= length ? length : (remain > 0 ? remain : 0);
  227. if (size > 0)
  228. {
  229. ushort[] bf = new ushort[size];
  230. Array.Copy(tmp.ShortValue, headAddr, bf, 0, bf.Length);
  231. return MCProtocol.Ushort2Byte(bf);
  232. }
  233. else
  234. return null;
  235. }
  236. }
  237. PlcBuffer buffer = _buffers.Find(x => x.Type == ioType);
  238. if (buffer == null)
  239. {
  240. return null;
  241. }
  242. byte[] result = null;
  243. if (ioType == IoType.DI)
  244. {
  245. bool[] value = buffer.BoolValue;
  246. int size = (value.Length + 1) / 2;
  247. result = new byte[size];
  248. for (int i = 0; i < size; i++)
  249. {
  250. if (value[i * 2 + 0])
  251. result[i] += 0x10;
  252. if ((i * 2 + 1) < value.Length)
  253. {
  254. if (value[i * 2 + 1])
  255. result[i] += 0x01;
  256. }
  257. }
  258. //result = MCProtocol.TransBoolArrayToByteData(buffer.BoolValue);
  259. }
  260. else
  261. {
  262. result = MCProtocol.Ushort2Byte(buffer.ShortValue);
  263. }
  264. return result;
  265. }
  266. }
  267. }