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];
///
/// 写DO锁
///
private object _writeDOLocker = new object();
///
/// 写AO锁
///
private object _writeAOLocker = new object();
public WagoSocketSimulator(int port):base(port)
{
InitializeData();
}
///
/// 初始化数组数据
///
private void InitializeData()
{
AIShorts[3] = 0x1388;
DIBytes[2] = 0x01;
}
#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;
}
}
}