WagoSocketSimulator.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. using Aitex.Core.RT.Device;
  2. using MECF.Framework.Common.Net;
  3. using MECF.Framework.Simulator.Core.Driver;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Diagnostics.Eventing.Reader;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. using System.Timers;
  12. namespace CyberX8_Simulator.Devices
  13. {
  14. public class WagoSocketSimulator : SocketDeviceSimulator
  15. {
  16. private const short WRITE_DO_STARTADDRESS = 0x0200;
  17. private const short WRITE_AO_STARTADDRESS = 0x0200;
  18. //键是名字,值是对应数据所在的位置 注意:要和WagoControlCfg里面的地址顺序对上
  19. private Dictionary<string, int> DONameIndexDic;
  20. private Dictionary<string, int> DINameIndexDic;
  21. private Dictionary<string, int> AINameIndexDic;
  22. private Dictionary<string, int> AONameIndexDic;
  23. private IByteTransform byteTransform = new BigEndianByteTransformBase();
  24. private byte[] DOBytes = new byte[100];
  25. private short[] AOShorts = new short[50];
  26. private byte[] DIBytes = new byte[100];
  27. private short[] AIShorts = new short[50];
  28. /// <summary>
  29. /// 写DO锁
  30. /// </summary>
  31. private object _writeDOLocker = new object();
  32. /// <summary>
  33. /// 写AO锁
  34. /// </summary>
  35. private object _writeAOLocker = new object();
  36. public WagoSocketSimulator(int port):base(port)
  37. {
  38. SimulatorCommManager.Instance.OnUpdateVariableValueChanged += UpdataDataCausedByOtherModule;
  39. InitializeData(port);
  40. }
  41. private void UpdataDataCausedByOtherModule(string name,bool value)
  42. {
  43. if (AINameIndexDic.ContainsKey(name))
  44. {
  45. if (value)
  46. {
  47. AIShorts[AINameIndexDic[name]] = 0x2710;
  48. }
  49. else
  50. {
  51. AIShorts[AINameIndexDic[name]] = 0x00;
  52. }
  53. }
  54. }
  55. /// <summary>
  56. /// 初始化字典
  57. /// </summary>
  58. private void InitializeData(int port)
  59. {
  60. DONameIndexDic = new Dictionary<string, int>
  61. {{"c_System_Alarm",0 },
  62. {"c_Pole_Red",1},
  63. {"c_Pole_Amber",2},
  64. {"c_Pole_Green",3},
  65. {"c_Pole_Blue",4},
  66. {"c_System_Alarm2",5},
  67. {"c_BACKSIDE_PRESSURE_TEST",6},
  68. {"c_VACUUM_TEST",7},
  69. {"DO8",8},
  70. {"DO9",9},
  71. {"DO10",10},
  72. {"DO11",11},
  73. {"DO12",12},
  74. {"DO13",13},
  75. {"DO14",14},
  76. {"DO15",15},
  77. {"DO16",16},
  78. {"DO17",17},
  79. {"DO18",18},
  80. {"DO19",19},
  81. {"DO20",20},
  82. {"DO21",21}};
  83. DINameIndexDic = new Dictionary<string, int>
  84. {{"r_Cassette_1_150",0 },
  85. {"r_Cassette_1_100",1},
  86. {"r_Cassette_1_200",2},
  87. {"r_Cassette_2_150",3},
  88. {"r_Cassette_2_100",4},
  89. {"r_Cassette_2_200",5},
  90. {"r_Cassette_3_150",6},
  91. {"r_Cassette_3_100",7},
  92. {"r_Cassette_3_200",8 },
  93. {"r_Dummy_1_150",9},
  94. {"r_Dummy_1_100",10},
  95. {"r_Dummy_1_200",11},
  96. {"r_Dummy_2_150",12},
  97. {"r_Dummy_2_100",13},
  98. {"r_Dummy_2_200",14},
  99. {"DI15",15},
  100. {"r_LoaderA_Wafer_Present",16},
  101. {"r_LoaderB_Wafer_Present",17},
  102. {"r_Cathode_Present",18},
  103. {"DI19",19},
  104. {"DI20",20},
  105. {"DI21",21},
  106. {"DI22",22},
  107. {"DI23",23},
  108. {"DI24",24},
  109. {"DI25",25},
  110. {"r_LOADERA_CRS_CURTAIN_1",26},
  111. {"r_LOADERA_CRS_CURTAIN_2",27},
  112. {"r_LOADERA_CRS_CURTAIN_3",28},
  113. {"r_LOADERA_CRS_CURTAIN_4",29},
  114. {"r_LOADERA_CRS_CURTAIN_5",30},
  115. {"r_LOADERA_CRS_CURTAIN_6",31}};
  116. AINameIndexDic = new Dictionary<string, int>
  117. {{"AI1",0 },
  118. {"AI2",1},
  119. {"AI3",2},
  120. {"AI4",3},
  121. {"r_LoaderA_LS_Vacuum_anlg",4},
  122. {"r_LoaderB_LS_Vacuum_anlg",5},
  123. {"AI6",6},
  124. {"r_LOADER_GasFlowSensor_FLOW",7},
  125. {"r_LOADERA_BERNOULLI_PRESSURE",8},
  126. {"r_LOADERB_BERNOULLI_PRESSURE",9},
  127. {"r_LOADERA_CHUCK_BLADDER",10},
  128. {"r_LOADERB_CHUCK_BLADDER",11},
  129. {"r_LOADERA_WS_BLADDER_PRESSURE",12},
  130. {"r_LOADERB_WS_BLADDER_PRESSURE",13},
  131. {"r_SPUF_VAC",14},
  132. {"r_LOADER_GasFlowSensor_VACUUM",15},};
  133. AONameIndexDic = new Dictionary<string, int>
  134. {{"AO1",0},
  135. {"AO2",1},
  136. {"AO3",2},
  137. {"AO4",3},
  138. {"AO5",4},
  139. {"AO6",5},
  140. {"AO7",6},
  141. {"AO8",7},
  142. {"AO9",8},
  143. {"AO10",9},
  144. {"AO11",10},
  145. {"AO12",11},
  146. {"AO13",12},
  147. {"AO14",13},
  148. {"AO15",14},
  149. {"AO16",15}};
  150. }
  151. #region 公共方法
  152. public void UpdataDOBytes(string name,int value)
  153. {
  154. if (DONameIndexDic.ContainsKey(name))
  155. {
  156. if (DONameIndexDic[name] < DOBytes.Length)
  157. {
  158. DOBytes[DONameIndexDic[name]] = value == 0 ? (byte)0 : (byte)1;
  159. }
  160. }
  161. }
  162. public void UpdataDIBytes(string name, int value)
  163. {
  164. if (DINameIndexDic.ContainsKey(name))
  165. {
  166. if (DINameIndexDic[name] < DIBytes.Length)
  167. {
  168. DIBytes[DINameIndexDic[name]] = value == 0 ? (byte)0 : (byte)1;
  169. }
  170. }
  171. }
  172. public void UpdataAOShorts(string name, int value)
  173. {
  174. if (AONameIndexDic.ContainsKey(name))
  175. {
  176. string hexValue = value.ToString("X2");
  177. try
  178. {
  179. short result = Convert.ToInt16(hexValue, 16);
  180. if (AONameIndexDic[name] < AOShorts.Length)
  181. {
  182. AOShorts[AONameIndexDic[name]] = result;
  183. }
  184. }
  185. catch (FormatException)
  186. {
  187. }
  188. }
  189. }
  190. public void UpdataAIShorts(string name, int value)
  191. {
  192. if (AINameIndexDic.ContainsKey(name))
  193. {
  194. string hexValue = value.ToString("X2");
  195. try
  196. {
  197. short result = Convert.ToInt16(hexValue, 16);
  198. if(AINameIndexDic[name] < AIShorts.Length)
  199. {
  200. AIShorts[AINameIndexDic[name]] = result;
  201. }
  202. }
  203. catch (FormatException)
  204. {
  205. }
  206. }
  207. }
  208. #endregion
  209. #region 功能方法
  210. /// <summary>
  211. /// 将长度为8的二进制byte数组转成对应十六进制byte值(大端模式)
  212. /// </summary>
  213. /// <param name="byteArray"></param>
  214. /// <returns></returns>
  215. public byte ConvertByteArrayToHex(byte[] byteArray)
  216. {
  217. byte result = 0;
  218. // 先将 byte 数组转换为二进制数
  219. int binaryValue = 0;
  220. for (int i = 0; i < 8; i++)
  221. {
  222. binaryValue |= (byteArray[i] << (7 - i));
  223. }
  224. // 逆转二进制数
  225. int reversedValue = 0;
  226. for (int i = 0; i < 8; i++)
  227. {
  228. reversedValue |= ((binaryValue >> i) & 1) << (7 - i);
  229. }
  230. // 转换为十六进制byte
  231. if (byte.TryParse(reversedValue.ToString("X2"), System.Globalization.NumberStyles.HexNumber, null, out result))
  232. {
  233. return result;
  234. }
  235. return 0;
  236. }
  237. /// <summary>
  238. /// 将short数组转成长度两倍的byte数组
  239. /// </summary>
  240. /// <param name="shortArray"></param>
  241. /// <returns></returns>
  242. private byte[] ConvertShortArrayToByteArray(short[] shortArray)
  243. {
  244. byte[] byteArray = new byte[shortArray.Length * 2];
  245. for (int i = 0; i < shortArray.Length; i++)
  246. {
  247. byte[] tempBytes = BitConverter.GetBytes(shortArray[i]);
  248. Array.Copy(tempBytes, 0, byteArray, i * 2, 2);
  249. }
  250. return byteArray;
  251. }
  252. #endregion
  253. protected override void ProcessUnsplitMessage(byte[] data)
  254. {
  255. byte command = data[7];
  256. if (command == 0x01) //读DO
  257. {
  258. short flag = byteTransform.TransInt16(data, 0);
  259. byte channel = data[6];
  260. short startAddress = byteTransform.TransInt16(data, 8);
  261. short bitCount = byteTransform.TransInt16(data, 10);
  262. byte byteCount = (byte)(bitCount / 8 + 1);
  263. byte[] bytes = new byte[byteCount];
  264. for(int i = 0; i < byteCount;i++)
  265. {
  266. byte[] tempbytes = new byte[8];
  267. Array.Copy(DOBytes,8 * i, tempbytes, 0, 8);
  268. bytes[i] = ConvertByteArrayToHex(tempbytes);
  269. }
  270. OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes));
  271. return;
  272. }
  273. else if(command == 0x03)//读AO
  274. {
  275. short flag = byteTransform.TransInt16(data, 0);
  276. byte channel = data[6];
  277. short startAddress = byteTransform.TransInt16(data, 8);
  278. short registerCount = byteTransform.TransInt16(data, 10);
  279. short[] shorts = new short[registerCount];//获取指定寄存器里的内容
  280. Array.Copy(AOShorts, 0, shorts, 0, registerCount);
  281. byte[] bytes = new byte[registerCount * 2];
  282. bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组长度两倍的bytes数组中
  283. OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes));
  284. return;
  285. }
  286. else if (command == 0x02)//读DI
  287. {
  288. short flag = byteTransform.TransInt16(data, 0);
  289. byte channel = data[6];
  290. short startAddress = byteTransform.TransInt16(data, 8);
  291. short bitCount = byteTransform.TransInt16(data, 10);
  292. byte byteCount = (byte)(bitCount / 8 + 1);
  293. byte[] bytes = new byte[byteCount];
  294. for (int i = 0; i < byteCount; i++)
  295. {
  296. byte[] tempbytes = new byte[8];
  297. Array.Copy(DIBytes, 8 * i, tempbytes, 0, 8);
  298. bytes[i] = ConvertByteArrayToHex(tempbytes);
  299. }
  300. OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes));
  301. return;
  302. }
  303. else if (command == 0x04)//读AI
  304. {
  305. short flag = byteTransform.TransInt16(data, 0);
  306. byte channel = data[6];
  307. short startAddress = byteTransform.TransInt16(data, 8);
  308. short registerCount = byteTransform.TransInt16(data, 10);
  309. short[] shorts = new short[registerCount];//获取指定寄存器里的内容
  310. Array.Copy(AIShorts, 0, shorts, 0, registerCount);
  311. byte[] bytes = new byte[registerCount * 2];
  312. bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组两倍的bytes数组中
  313. OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes));
  314. return;
  315. }
  316. else if (command == 0x05)//写DO
  317. {
  318. short startAddress = byteTransform.TransInt16(data, 8);
  319. if (startAddress > 0x03FF || startAddress < WRITE_DO_STARTADDRESS)
  320. {
  321. short flag = byteTransform.TransInt16(data, 0);
  322. byte channel = data[6];
  323. OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误
  324. return;
  325. }
  326. int position = startAddress - WRITE_DO_STARTADDRESS;
  327. bool status = data[10] == 0xFF ? true : false;
  328. lock (_writeDOLocker)
  329. {
  330. DOBytes[position] = status ? (byte)1 : (byte)0;
  331. }
  332. OnWriteMessage(data); //原消息返回
  333. return;
  334. }
  335. else if (command == 0x06)//写AO
  336. {
  337. short startAddress = byteTransform.TransInt16(data, 8);
  338. if(startAddress > 0x02FF || startAddress < WRITE_AO_STARTADDRESS)
  339. {
  340. short flag = byteTransform.TransInt16(data, 0);
  341. byte channel = data[6];
  342. OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误
  343. return;
  344. }
  345. int position = startAddress - WRITE_AO_STARTADDRESS;
  346. short value = byteTransform.TransInt16(data, 10);
  347. lock (_writeAOLocker)
  348. {
  349. AOShorts[position] = value;
  350. }
  351. OnWriteMessage(data); //原消息返回
  352. return;
  353. }
  354. else
  355. {
  356. short flag = byteTransform.TransInt16(data, 0);
  357. byte channel = data[6];
  358. OnWriteMessage(CreateError(flag, channel, command, 0x01)); //指令错误
  359. return;
  360. }
  361. }
  362. /// <summary>
  363. /// 回复读数字量
  364. /// </summary>
  365. /// <param name="flag"></param>
  366. /// <param name="channel"></param>
  367. /// <param name="command"></param>
  368. /// <param name="byteCount"></param>
  369. /// <param name="values"></param>
  370. /// <returns></returns>
  371. private byte[] CreateReadDigitalResponse(short flag, byte channel, byte command, byte byteCount, byte[] values)
  372. {
  373. byte[] bytes = new byte[7 + 2 + values.Length]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+values.length个字节
  374. Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
  375. bytes[2] = 0x00;
  376. bytes[3] = 0x00;
  377. short dataLength = (short)(3 + values.Length);
  378. Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2);
  379. bytes[6] = channel;
  380. bytes[7] = command;
  381. bytes[8] = byteCount;
  382. Array.Copy(values, 0, bytes, 9, values.Length);
  383. return bytes;
  384. }
  385. /// <summary>
  386. /// 回复读模拟量
  387. /// </summary>
  388. /// <param name="flag"></param>
  389. /// <param name="channel"></param>
  390. /// <param name="command"></param>
  391. /// <param name="registerCount"></param>
  392. /// <param name="values"></param>
  393. /// <returns></returns>
  394. private byte[] CreateReadAnalogyResponse(short flag, byte channel, byte command, byte registerCount, byte[] values)
  395. {
  396. byte[] bytes = new byte[7 + 2 + 2 * registerCount]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+registerCount*2个字节(一个寄存器占两个字节)
  397. Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
  398. bytes[2] = 0x00;
  399. bytes[3] = 0x00;
  400. short dataLength = (short)(3 + 2 * registerCount);
  401. Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2);
  402. bytes[6] = channel;
  403. bytes[7] = command;
  404. bytes[8] = (byte)(2 * registerCount);
  405. Array.Copy(values, 0, bytes, 9, values.Length);
  406. return bytes;
  407. }
  408. /// <summary>
  409. /// 错误回复
  410. /// </summary>
  411. /// <param name="flag"></param>
  412. /// <param name="channel"></param>
  413. /// <param name="command"></param>
  414. /// <param name="error"></param>
  415. /// <returns></returns>
  416. private byte[] CreateError(short flag, byte channel, byte command, byte error)
  417. {
  418. byte[] bytes = new byte[9];
  419. Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2);
  420. bytes[2] = 0x00;
  421. bytes[3] = 0x00;
  422. bytes[4] = 0x00;
  423. bytes[5] = 0x03;
  424. bytes[6] = channel;
  425. bytes[7] = (byte)(command | 0x80);
  426. bytes[8] = error;
  427. return bytes;
  428. }
  429. }
  430. }