WagoSocketSimulator.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. using MECF.Framework.Common.Net;
  2. using MECF.Framework.Simulator.Core.Driver;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. namespace CyberX8_Simulator.Devices
  10. {
  11. public class WagoSocketSimulator : SocketDeviceSimulator
  12. {
  13. private const short WRITE_DO_STARTADDRESS = 0x0200;
  14. private const short WRITE_AO_STARTADDRESS = 0x0200;
  15. private IByteTransform byteTransform = new BigEndianByteTransformBase();
  16. private byte[] DOBytes = new byte[100];
  17. //键是名字,值是对应DoByte所在的位置
  18. private Dictionary<string,int> DONameIndexDic = new Dictionary<string, int>
  19. {{"DO0",0 },{"c_LoaderA_LS_Vacuum",1} };
  20. private Dictionary<string, int> DINameIndexDic = new Dictionary<string, int>
  21. {{"DI0",0 },{"DI1",1} };
  22. private short[] AOShorts = new short[50];
  23. private byte[] DIBytes = new byte[100];
  24. private short[] AIShorts = new short[50];
  25. /// <summary>
  26. /// 写DO锁
  27. /// </summary>
  28. private object _writeDOLocker = new object();
  29. /// <summary>
  30. /// 写AO锁
  31. /// </summary>
  32. private object _writeAOLocker = new object();
  33. public WagoSocketSimulator(int port):base(port)
  34. {
  35. InitializeData();
  36. }
  37. /// <summary>
  38. /// 初始化数组数据
  39. /// </summary>
  40. private void InitializeData()
  41. {
  42. AIShorts[3] = 0x1388;
  43. DIBytes[2] = 0x01;
  44. }
  45. #region 公共方法
  46. public void UpdataDOBytes(string name,int value)
  47. {
  48. if (DONameIndexDic.ContainsKey(name))
  49. {
  50. DOBytes[DONameIndexDic[name]] = value == 0 ? (byte)0 : (byte)1;
  51. }
  52. }
  53. public void UpdataDIBytes(string name, int value)
  54. {
  55. if (DINameIndexDic.ContainsKey(name))
  56. {
  57. DIBytes[DONameIndexDic[name]] = value == 0 ? (byte)0 : (byte)1;
  58. }
  59. }
  60. public void UpdataAOShorts(string name, int value)
  61. {
  62. }
  63. public void UpdataAIShorts(string name, int value)
  64. {
  65. }
  66. #endregion
  67. #region 功能方法
  68. /// <summary>
  69. /// 将长度为8的二进制byte数组转成对应十六进制byte值(大端模式)
  70. /// </summary>
  71. /// <param name="byteArray"></param>
  72. /// <returns></returns>
  73. public byte ConvertByteArrayToHex(byte[] byteArray)
  74. {
  75. byte result = 0;
  76. // 先将 byte 数组转换为二进制数
  77. int binaryValue = 0;
  78. for (int i = 0; i < 8; i++)
  79. {
  80. binaryValue |= (byteArray[i] << (7 - i));
  81. }
  82. // 逆转二进制数
  83. int reversedValue = 0;
  84. for (int i = 0; i < 8; i++)
  85. {
  86. reversedValue |= ((binaryValue >> i) & 1) << (7 - i);
  87. }
  88. // 转换为十六进制byte
  89. if (byte.TryParse(reversedValue.ToString("X2"), System.Globalization.NumberStyles.HexNumber, null, out result))
  90. {
  91. return result;
  92. }
  93. return 0;
  94. }
  95. /// <summary>
  96. /// 将short数组转成长度两倍的byte数组
  97. /// </summary>
  98. /// <param name="shortArray"></param>
  99. /// <returns></returns>
  100. private byte[] ConvertShortArrayToByteArray(short[] shortArray)
  101. {
  102. byte[] byteArray = new byte[shortArray.Length * 2];
  103. for (int i = 0; i < shortArray.Length; i++)
  104. {
  105. byte[] tempBytes = BitConverter.GetBytes(shortArray[i]);
  106. Array.Copy(tempBytes, 0, byteArray, i * 2, 2);
  107. }
  108. return byteArray;
  109. }
  110. #endregion
  111. protected override void ProcessUnsplitMessage(byte[] data)
  112. {
  113. byte command = data[7];
  114. if (command == 0x01) //读DO
  115. {
  116. short flag = byteTransform.TransInt16(data, 0);
  117. byte channel = data[6];
  118. short startAddress = byteTransform.TransInt16(data, 8);
  119. short bitCount = byteTransform.TransInt16(data, 10);
  120. byte byteCount = (byte)(bitCount / 8 + 1);
  121. byte[] bytes = new byte[byteCount];
  122. for(int i = 0; i < byteCount;i++)
  123. {
  124. byte[] tempbytes = new byte[8];
  125. Array.Copy(DOBytes,8 * i, tempbytes, 0, 8);
  126. bytes[i] = ConvertByteArrayToHex(tempbytes);
  127. }
  128. OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes));
  129. return;
  130. }
  131. else if(command == 0x03)//读AO
  132. {
  133. short flag = byteTransform.TransInt16(data, 0);
  134. byte channel = data[6];
  135. short startAddress = byteTransform.TransInt16(data, 8);
  136. short registerCount = byteTransform.TransInt16(data, 10);
  137. short[] shorts = new short[registerCount];//获取指定寄存器里的内容
  138. Array.Copy(AOShorts, 0, shorts, 0, registerCount);
  139. byte[] bytes = new byte[registerCount * 2];
  140. bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组长度两倍的bytes数组中
  141. OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes));
  142. return;
  143. }
  144. else if (command == 0x02)//读DI
  145. {
  146. short flag = byteTransform.TransInt16(data, 0);
  147. byte channel = data[6];
  148. short startAddress = byteTransform.TransInt16(data, 8);
  149. short bitCount = byteTransform.TransInt16(data, 10);
  150. byte byteCount = (byte)(bitCount / 8 + 1);
  151. byte[] bytes = new byte[byteCount];
  152. for (int i = 0; i < byteCount; i++)
  153. {
  154. byte[] tempbytes = new byte[8];
  155. Array.Copy(DIBytes, 8 * i, tempbytes, 0, 8);
  156. bytes[i] = ConvertByteArrayToHex(tempbytes);
  157. }
  158. OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes));
  159. return;
  160. }
  161. else if (command == 0x04)//读AI
  162. {
  163. short flag = byteTransform.TransInt16(data, 0);
  164. byte channel = data[6];
  165. short startAddress = byteTransform.TransInt16(data, 8);
  166. short registerCount = byteTransform.TransInt16(data, 10);
  167. short[] shorts = new short[registerCount];//获取指定寄存器里的内容
  168. Array.Copy(AIShorts, 0, shorts, 0, registerCount);
  169. byte[] bytes = new byte[registerCount * 2];
  170. bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组两倍的bytes数组中
  171. OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes));
  172. return;
  173. }
  174. else if (command == 0x05)//写DO
  175. {
  176. short startAddress = byteTransform.TransInt16(data, 8);
  177. if (startAddress > 0x03FF || startAddress < WRITE_DO_STARTADDRESS)
  178. {
  179. short flag = byteTransform.TransInt16(data, 0);
  180. byte channel = data[6];
  181. OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误
  182. return;
  183. }
  184. int position = startAddress - WRITE_DO_STARTADDRESS;
  185. bool status = data[10] == 0xFF ? true : false;
  186. lock (_writeDOLocker)
  187. {
  188. DOBytes[position] = status ? (byte)1 : (byte)0;
  189. }
  190. OnWriteMessage(data); //原消息返回
  191. return;
  192. }
  193. else if (command == 0x06)//写AO
  194. {
  195. short startAddress = byteTransform.TransInt16(data, 8);
  196. if(startAddress > 0x02FF || startAddress < WRITE_AO_STARTADDRESS)
  197. {
  198. short flag = byteTransform.TransInt16(data, 0);
  199. byte channel = data[6];
  200. OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误
  201. return;
  202. }
  203. int position = startAddress - WRITE_AO_STARTADDRESS;
  204. short value = byteTransform.TransInt16(data, 10);
  205. lock (_writeAOLocker)
  206. {
  207. AOShorts[position] = value;
  208. }
  209. OnWriteMessage(data); //原消息返回
  210. return;
  211. }
  212. else
  213. {
  214. short flag = byteTransform.TransInt16(data, 0);
  215. byte channel = data[6];
  216. OnWriteMessage(CreateError(flag, channel, command, 0x01)); //指令错误
  217. return;
  218. }
  219. }
  220. /// <summary>
  221. /// 回复读数字量
  222. /// </summary>
  223. /// <param name="flag"></param>
  224. /// <param name="channel"></param>
  225. /// <param name="command"></param>
  226. /// <param name="byteCount"></param>
  227. /// <param name="values"></param>
  228. /// <returns></returns>
  229. private byte[] CreateReadDigitalResponse(short flag, byte channel, byte command, byte byteCount, byte[] values)
  230. {
  231. byte[] bytes = new byte[7 + 2 + values.Length]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+values.length个字节
  232. Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
  233. bytes[2] = 0x00;
  234. bytes[3] = 0x00;
  235. short dataLength = (short)(3 + values.Length);
  236. Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2);
  237. bytes[6] = channel;
  238. bytes[7] = command;
  239. bytes[8] = byteCount;
  240. Array.Copy(values, 0, bytes, 9, values.Length);
  241. return bytes;
  242. }
  243. /// <summary>
  244. /// 回复读模拟量
  245. /// </summary>
  246. /// <param name="flag"></param>
  247. /// <param name="channel"></param>
  248. /// <param name="command"></param>
  249. /// <param name="registerCount"></param>
  250. /// <param name="values"></param>
  251. /// <returns></returns>
  252. private byte[] CreateReadAnalogyResponse(short flag, byte channel, byte command, byte registerCount, byte[] values)
  253. {
  254. byte[] bytes = new byte[7 + 2 + 2 * registerCount]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+registerCount*2个字节(一个寄存器占两个字节)
  255. Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
  256. bytes[2] = 0x00;
  257. bytes[3] = 0x00;
  258. short dataLength = (short)(3 + 2 * registerCount);
  259. Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2);
  260. bytes[6] = channel;
  261. bytes[7] = command;
  262. bytes[8] = (byte)(2 * registerCount);
  263. Array.Copy(values, 0, bytes, 9, values.Length);
  264. return bytes;
  265. }
  266. /// <summary>
  267. /// 错误回复
  268. /// </summary>
  269. /// <param name="flag"></param>
  270. /// <param name="channel"></param>
  271. /// <param name="command"></param>
  272. /// <param name="error"></param>
  273. /// <returns></returns>
  274. private byte[] CreateError(short flag, byte channel, byte command, byte error)
  275. {
  276. byte[] bytes = new byte[9];
  277. Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
  278. bytes[2] = 0x00;
  279. bytes[3] = 0x00;
  280. bytes[4] = 0x00;
  281. bytes[5] = 0x03;
  282. bytes[6] = channel;
  283. bytes[7] = (byte)(command | 0x80);
  284. bytes[8] = error;
  285. return bytes;
  286. }
  287. }
  288. }