|
@@ -0,0 +1,232 @@
|
|
|
+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;
|
|
|
+
|
|
|
+
|
|
|
+ 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];
|
|
|
+ /// <summary>
|
|
|
+ /// 写DO锁
|
|
|
+ /// </summary>
|
|
|
+ private object _writeDOLocker = new object();
|
|
|
+ /// <summary>
|
|
|
+ /// 写AO锁
|
|
|
+ /// </summary>
|
|
|
+ private object _writeAOLocker = new object();
|
|
|
+
|
|
|
+ public WagoSocketSimulator(int port):base(port)
|
|
|
+ {
|
|
|
+ InitializeData();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 初始化数组数据
|
|
|
+ /// </summary>
|
|
|
+ private void InitializeData()
|
|
|
+ {
|
|
|
+ AIShorts[3] = 0x1388;
|
|
|
+ }
|
|
|
+
|
|
|
+ #region 功能方法
|
|
|
+ /// <summary>
|
|
|
+ /// 将长度为8的二进制byte数组转成对应十六进制byte值(大端模式)
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="byteArray"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 将short数组转成长度两倍的byte数组
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="shortArray"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ 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);
|
|
|
+ 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);
|
|
|
+ int position = startAddress - WRITE_AO_STARTADDRESS;
|
|
|
+ short value = byteTransform.TransInt16(data, 10);
|
|
|
+ lock (_writeAOLocker)
|
|
|
+ {
|
|
|
+ AOShorts[position] = value;
|
|
|
+ }
|
|
|
+ OnWriteMessage(data); //原消息返回
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 回复读数字量
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="flag"></param>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="command"></param>
|
|
|
+ /// <param name="byteCount"></param>
|
|
|
+ /// <param name="values"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 回复读模拟量
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="flag"></param>
|
|
|
+ /// <param name="channel"></param>
|
|
|
+ /// <param name="command"></param>
|
|
|
+ /// <param name="registerCount"></param>
|
|
|
+ /// <param name="values"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+}
|