WagoSocketSimulator.cs 14 KB

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