using Aitex.Core.RT.Device; using MECF.Framework.Common.Net; using MECF.Framework.Simulator.Core.Driver; using System; using System.Collections.Generic; using System.Diagnostics.Eventing.Reader; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Timers; namespace CyberX8_Simulator.Devices { public class WagoSocketSimulator : SocketDeviceSimulator { private const short WRITE_DO_STARTADDRESS = 0x0200; private const short WRITE_AO_STARTADDRESS = 0x0200; //键是名字,值是对应数据所在的位置 注意:要和WagoControlCfg里面的地址顺序对上 private Dictionary DONameIndexDic; private Dictionary DINameIndexDic; private Dictionary AINameIndexDic; private Dictionary AONameIndexDic; private IByteTransform byteTransform = new BigEndianByteTransformBase(); private byte[] DOBytes = new byte[100]; private short[] AOShorts = new short[50]; private byte[] DIBytes = new byte[100]; private short[] AIShorts = new short[50]; /// /// 写DO锁 /// private object _writeDOLocker = new object(); /// /// 写AO锁 /// private object _writeAOLocker = new object(); public WagoSocketSimulator(int port):base(port) { SimulatorCommManager.Instance.OnUpdateVariableValueChanged += UpdataDataCausedByOtherModule; InitializeData(port); } private void UpdataDataCausedByOtherModule(string name,bool value) { if (AINameIndexDic.ContainsKey(name)) { if (value) { AIShorts[AINameIndexDic[name]] = 0x2710; } else { AIShorts[AINameIndexDic[name]] = 0x00; } } } /// /// 初始化字典 /// private void InitializeData(int port) { DONameIndexDic = new Dictionary {{"c_System_Alarm",0 }, {"c_Pole_Red",1}, {"c_Pole_Amber",2}, {"c_Pole_Green",3}, {"c_Pole_Blue",4}, {"c_System_Alarm2",5}, {"c_BACKSIDE_PRESSURE_TEST",6}, {"c_VACUUM_TEST",7}, {"DO8",8}, {"DO9",9}, {"DO10",10}, {"DO11",11}, {"DO12",12}, {"DO13",13}, {"DO14",14}, {"DO15",15}, {"DO16",16}, {"DO17",17}, {"DO18",18}, {"DO19",19}, {"DO20",20}, {"DO21",21}}; DINameIndexDic = new Dictionary {{"r_Cassette_1_150",0 }, {"r_Cassette_1_100",1}, {"r_Cassette_1_200",2}, {"r_Cassette_2_150",3}, {"r_Cassette_2_100",4}, {"r_Cassette_2_200",5}, {"r_Cassette_3_150",6}, {"r_Cassette_3_100",7}, {"r_Cassette_3_200",8 }, {"r_Dummy_1_150",9}, {"r_Dummy_1_100",10}, {"r_Dummy_1_200",11}, {"r_Dummy_2_150",12}, {"r_Dummy_2_100",13}, {"r_Dummy_2_200",14}, {"DI15",15}, {"r_LoaderA_Wafer_Present",16}, {"r_LoaderB_Wafer_Present",17}, {"r_Cathode_Present",18}, {"DI19",19}, {"DI20",20}, {"DI21",21}, {"DI22",22}, {"DI23",23}, {"DI24",24}, {"DI25",25}, {"r_LOADERA_CRS_CURTAIN_1",26}, {"r_LOADERA_CRS_CURTAIN_2",27}, {"r_LOADERA_CRS_CURTAIN_3",28}, {"r_LOADERA_CRS_CURTAIN_4",29}, {"r_LOADERA_CRS_CURTAIN_5",30}, {"r_LOADERA_CRS_CURTAIN_6",31}}; AINameIndexDic = new Dictionary {{"AI1",0 }, {"AI2",1}, {"AI3",2}, {"AI4",3}, {"r_LoaderA_LS_Vacuum_anlg",4}, {"r_LoaderB_LS_Vacuum_anlg",5}, {"AI6",6}, {"r_LOADER_GasFlowSensor_FLOW",7}, {"r_LOADERA_BERNOULLI_PRESSURE",8}, {"r_LOADERB_BERNOULLI_PRESSURE",9}, {"r_LOADERA_CHUCK_BLADDER",10}, {"r_LOADERB_CHUCK_BLADDER",11}, {"r_LOADERA_WS_BLADDER_PRESSURE",12}, {"r_LOADERB_WS_BLADDER_PRESSURE",13}, {"r_SPUF_VAC",14}, {"r_LOADER_GasFlowSensor_VACUUM",15},}; AONameIndexDic = new Dictionary {{"AO1",0}, {"AO2",1}, {"AO3",2}, {"AO4",3}, {"AO5",4}, {"AO6",5}, {"AO7",6}, {"AO8",7}, {"AO9",8}, {"AO10",9}, {"AO11",10}, {"AO12",11}, {"AO13",12}, {"AO14",13}, {"AO15",14}, {"AO16",15}}; } #region 公共方法 public void UpdataDOBytes(string name,int value) { if (DONameIndexDic.ContainsKey(name)) { if (DONameIndexDic[name] < DOBytes.Length) { DOBytes[DONameIndexDic[name]] = value == 0 ? (byte)0 : (byte)1; } } } public void UpdataDIBytes(string name, int value) { if (DINameIndexDic.ContainsKey(name)) { if (DINameIndexDic[name] < DIBytes.Length) { DIBytes[DINameIndexDic[name]] = value == 0 ? (byte)0 : (byte)1; } } } public void UpdataAOShorts(string name, int value) { if (AONameIndexDic.ContainsKey(name)) { string hexValue = value.ToString("X2"); try { short result = Convert.ToInt16(hexValue, 16); if (AONameIndexDic[name] < AOShorts.Length) { AOShorts[AONameIndexDic[name]] = result; } } catch (FormatException) { } } } public void UpdataAIShorts(string name, int value) { if (AINameIndexDic.ContainsKey(name)) { string hexValue = value.ToString("X2"); try { short result = Convert.ToInt16(hexValue, 16); if(AINameIndexDic[name] < AIShorts.Length) { AIShorts[AINameIndexDic[name]] = result; } } catch (FormatException) { } } } #endregion #region 功能方法 /// /// 将长度为8的二进制byte数组转成对应十六进制byte值(大端模式) /// /// /// public byte ConvertByteArrayToHex(byte[] byteArray) { byte result = 0; // 先将 byte 数组转换为二进制数 int binaryValue = 0; for (int i = 0; i < 8; i++) { binaryValue |= (byteArray[i] << (7 - i)); } // 逆转二进制数 int reversedValue = 0; for (int i = 0; i < 8; i++) { reversedValue |= ((binaryValue >> i) & 1) << (7 - i); } // 转换为十六进制byte if (byte.TryParse(reversedValue.ToString("X2"), System.Globalization.NumberStyles.HexNumber, null, out result)) { return result; } return 0; } /// /// 将short数组转成长度两倍的byte数组 /// /// /// private byte[] ConvertShortArrayToByteArray(short[] shortArray) { byte[] byteArray = new byte[shortArray.Length * 2]; for (int i = 0; i < shortArray.Length; i++) { byte[] tempBytes = BitConverter.GetBytes(shortArray[i]); Array.Copy(tempBytes, 0, byteArray, i * 2, 2); } return byteArray; } #endregion protected override void ProcessUnsplitMessage(byte[] data) { byte command = data[7]; if (command == 0x01) //读DO { short flag = byteTransform.TransInt16(data, 0); byte channel = data[6]; short startAddress = byteTransform.TransInt16(data, 8); short bitCount = byteTransform.TransInt16(data, 10); byte byteCount = (byte)(bitCount / 8 + 1); byte[] bytes = new byte[byteCount]; for(int i = 0; i < byteCount;i++) { byte[] tempbytes = new byte[8]; Array.Copy(DOBytes,8 * i, tempbytes, 0, 8); bytes[i] = ConvertByteArrayToHex(tempbytes); } OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes)); return; } else if(command == 0x03)//读AO { short flag = byteTransform.TransInt16(data, 0); byte channel = data[6]; short startAddress = byteTransform.TransInt16(data, 8); short registerCount = byteTransform.TransInt16(data, 10); short[] shorts = new short[registerCount];//获取指定寄存器里的内容 Array.Copy(AOShorts, 0, shorts, 0, registerCount); byte[] bytes = new byte[registerCount * 2]; bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组长度两倍的bytes数组中 OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes)); return; } else if (command == 0x02)//读DI { short flag = byteTransform.TransInt16(data, 0); byte channel = data[6]; short startAddress = byteTransform.TransInt16(data, 8); short bitCount = byteTransform.TransInt16(data, 10); byte byteCount = (byte)(bitCount / 8 + 1); byte[] bytes = new byte[byteCount]; for (int i = 0; i < byteCount; i++) { byte[] tempbytes = new byte[8]; Array.Copy(DIBytes, 8 * i, tempbytes, 0, 8); bytes[i] = ConvertByteArrayToHex(tempbytes); } OnWriteMessage(CreateReadDigitalResponse(flag, channel, command, byteCount, bytes)); return; } else if (command == 0x04)//读AI { short flag = byteTransform.TransInt16(data, 0); byte channel = data[6]; short startAddress = byteTransform.TransInt16(data, 8); short registerCount = byteTransform.TransInt16(data, 10); short[] shorts = new short[registerCount];//获取指定寄存器里的内容 Array.Copy(AIShorts, 0, shorts, 0, registerCount); byte[] bytes = new byte[registerCount * 2]; bytes = ConvertShortArrayToByteArray(shorts); //转入长度为shorts数组两倍的bytes数组中 OnWriteMessage(CreateReadAnalogyResponse(flag, channel, command, (byte)registerCount, bytes)); return; } else if (command == 0x05)//写DO { short startAddress = byteTransform.TransInt16(data, 8); if (startAddress > 0x03FF || startAddress < WRITE_DO_STARTADDRESS) { short flag = byteTransform.TransInt16(data, 0); byte channel = data[6]; OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误 return; } int position = startAddress - WRITE_DO_STARTADDRESS; bool status = data[10] == 0xFF ? true : false; lock (_writeDOLocker) { DOBytes[position] = status ? (byte)1 : (byte)0; } OnWriteMessage(data); //原消息返回 return; } else if (command == 0x06)//写AO { short startAddress = byteTransform.TransInt16(data, 8); if(startAddress > 0x02FF || startAddress < WRITE_AO_STARTADDRESS) { short flag = byteTransform.TransInt16(data, 0); byte channel = data[6]; OnWriteMessage(CreateError(flag, channel, command, 0x02)); //地址错误 return; } int position = startAddress - WRITE_AO_STARTADDRESS; short value = byteTransform.TransInt16(data, 10); lock (_writeAOLocker) { AOShorts[position] = value; } OnWriteMessage(data); //原消息返回 return; } else { short flag = byteTransform.TransInt16(data, 0); byte channel = data[6]; OnWriteMessage(CreateError(flag, channel, command, 0x01)); //指令错误 return; } } /// /// 回复读数字量 /// /// /// /// /// /// /// private byte[] CreateReadDigitalResponse(short flag, byte channel, byte command, byte byteCount, byte[] values) { byte[] bytes = new byte[7 + 2 + values.Length]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+values.length个字节 Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2); bytes[2] = 0x00; bytes[3] = 0x00; short dataLength = (short)(3 + values.Length); Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2); bytes[6] = channel; bytes[7] = command; bytes[8] = byteCount; Array.Copy(values, 0, bytes, 9, values.Length); return bytes; } /// /// 回复读模拟量 /// /// /// /// /// /// /// private byte[] CreateReadAnalogyResponse(short flag, byte channel, byte command, byte registerCount, byte[] values) { byte[] bytes = new byte[7 + 2 + 2 * registerCount]; //回复字节长度,前面7个字节固定长度 + functionCode一个字节 + byteCount一个字节+registerCount*2个字节(一个寄存器占两个字节) Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2); bytes[2] = 0x00; bytes[3] = 0x00; short dataLength = (short)(3 + 2 * registerCount); Array.Copy(byteTransform.GetBytes(dataLength), 0, bytes, 4, 2); bytes[6] = channel; bytes[7] = command; bytes[8] = (byte)(2 * registerCount); Array.Copy(values, 0, bytes, 9, values.Length); return bytes; } /// /// 错误回复 /// /// /// /// /// /// private byte[] CreateError(short flag, byte channel, byte command, byte error) { byte[] bytes = new byte[9]; Array.Copy(byteTransform.GetBytes(flag), 0, bytes, 0, 2); bytes[2] = 0x00; bytes[3] = 0x00; bytes[4] = 0x00; bytes[5] = 0x03; bytes[6] = channel; bytes[7] = (byte)(command | 0x80); bytes[8] = error; return bytes; } } }