using MECF.Framework.Common.Net; using MECF.Framework.Simulator.Core.Driver; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; 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 = new Dictionary {{"DO0",0 },{"c_LoaderA_LS_Vacuum",1} }; private Dictionary DINameIndexDic = new Dictionary {{"r_DRIP_TRAY_FLUID_DETECTION",19 },{"DI1",1} }; private Dictionary AINameIndexDic = new Dictionary {{"r_LoaderA_LS_Vacuum_anlg",0 },{"AI1",1} }; private Dictionary AONameIndexDic = new Dictionary {{"AO0",0 },{"AO1",1} }; 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) { InitializeData(); } /// /// 初始化数组数据 /// private void InitializeData() { AIShorts[0] = 0x1388; } #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; } } }