using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static EasyModbus.TCPHandler;
namespace McProtocol.Mitsubishi
{
public class McProtocolTcp
{
///
/// 使用的指令框架
///
public McFrame CommandFrame { get; set; }
private McCommand Command { get; set; }
///
/// 主机名或者IP地址
///
public string HostName { get; set; }
///
/// 端口号
///
public int PortNumber { get; set; }
public int Device { private set; get; }
private const int BlockSize = 0x0010;
private TcpClient Client { get; set; }
private NetworkStream Stream { get; set; }
// 是否连接
public bool Connected
{
get
{
return Client.Connected;
}
}
///
/// 构造函数
///
public McProtocolTcp() : this("", 0, McFrame.MC3E)
{
}
///
/// 构造函数
///
///
///
///
public McProtocolTcp(string iHostName, int iPortNumber, McFrame frame)
{
CommandFrame = frame;
Client = new TcpClient();
//C70 = MC3E
HostName = iHostName;
PortNumber = iPortNumber;
}
///
/// 后处理
///
public void Dispose()
{
TcpClient c = Client;
if (c.Connected)
{
c.Close();
}
}
public void Open()
{
if (!Client.Connected)
{
// 实现Keep Alive功能
var ka = new List(sizeof(uint) * 3);
ka.AddRange(BitConverter.GetBytes(1u));
ka.AddRange(BitConverter.GetBytes(45000u));
ka.AddRange(BitConverter.GetBytes(5000u));
Client.Client.IOControl(IOControlCode.KeepAliveValues, ka.ToArray(), null);
IAsyncResult asyncResult = Client.BeginConnect(HostName, PortNumber, null, null);
if (!asyncResult.AsyncWaitHandle.WaitOne(1000))
{
throw new Exception("连接超时");
}
Client.EndConnect(asyncResult);
Stream = Client.GetStream();
}
Command = new McCommand(CommandFrame);
}
public int SetBitDevice(string iDeviceName, int iSize, int[] iData)
{
PlcDeviceType type;
int addr;
GetDeviceCode(iDeviceName, out type, out addr);
return SetBitDevice(type, addr, iSize, iData);
}
public int SetBitDevice(PlcDeviceType iType, int iAddress, int iSize, int[] iData)
{
var type = iType;
var addr = iAddress;
var data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)type, (byte)iSize, (byte)(iSize >> 8) };
var d = (byte)iData[0];
var i = 0;
while (i < iData.Length)
{
if (i % 2 == 0)
{
d = (byte)iData[i];
d <<= 4;
}
else
{
d |= (byte)(iData[i] & 0x01);
data.Add(d);
}
++i;
}
if (i % 2 != 0)
{
data.Add(d);
}
int length = (int)Command.FrameType;// == McFrame.MC3E) ? 11 : 15;
byte[] sdCommand = Command.SetCommandMC3E(0x1401, 0x0001, data.ToArray());
byte[] rtResponse = TryExecution(sdCommand, length);
int rtCode = Command.SetResponse(rtResponse);
return rtCode;
}
public int GetBitDevice(string iDeviceName, int iSize, int[] oData)
{
PlcDeviceType type;
int addr;
GetDeviceCode(iDeviceName, out type, out addr);
return GetBitDevice(type, addr, iSize, oData);
}
public int GetBitDevice(PlcDeviceType iType, int iAddress, int iSize, int[] oData)
{
PlcDeviceType type = iType;
int addr = iAddress;
var data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)type, (byte)iSize, (byte)(iSize >> 8) };
byte[] sdCommand = Command.SetCommandMC3E(0x0401, 0x0001, data.ToArray());
int length = (Command.FrameType == McFrame.MC3E) ? 11 : 15;
byte[] rtResponse = TryExecution(sdCommand, length);
int rtCode = Command.SetResponse(rtResponse);
byte[] rtData = Command.Response;
for (int i = 0; i < iSize; ++i)
{
if (i % 2 == 0)
{
oData[i] = (rtCode == 0) ? ((rtData[i / 2] >> 4) & 0x01) : 0;
}
else
{
oData[i] = (rtCode == 0) ? (rtData[i / 2] & 0x01) : 0;
}
}
return rtCode;
}
public int WriteDeviceBlock(string iDeviceName, int iSize, ushort[] iData)
{
PlcDeviceType type;
int addr;
GetDeviceCode(iDeviceName, out type, out addr);
return WriteDeviceBlock(type, addr, iSize, iData);
}
public int WriteDeviceBlock(PlcDeviceType iType, int iAddress, int iSize, ushort[] iData)
{
PlcDeviceType type = iType;
int addr = iAddress;
List data;
List DeviceData = new List();
foreach (ushort t in iData)
{
byte[] value = BitConverter.GetBytes(t);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(value);
}
DeviceData.AddRange(value);
}
byte[] sdCommand;
int length;
switch (CommandFrame)
{
case McFrame.MC3E:
data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)type, (byte)iSize, (byte)(iSize >> 8) };
data.AddRange(DeviceData.ToArray());
sdCommand = Command.SetCommandMC3E(0x1401, 0x0000, data.ToArray());
length = 11;
break;
case McFrame.MC4E:
data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)type, (byte)iSize, (byte)(iSize >> 8) };
data.AddRange(DeviceData.ToArray());
sdCommand = Command.SetCommandMC4E(0x1401, 0x0000, data.ToArray());
length = 15;
break;
case McFrame.MC1E:
data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)(addr >> 24), 0x20, 0x44, (byte)iSize, 0x00 };
data.AddRange(DeviceData.ToArray());
//Add data
sdCommand = Command.SetCommandMC1E(0x03, data.ToArray());
length = 2;
break;
default:
throw new Exception("Message frame not supported");
}
//TEST take care of the writing
byte[] rtResponse = TryExecution(sdCommand, length);
int rtCode = Command.SetResponse(rtResponse);
return rtCode;
}
public byte[] ReadDeviceBlock(string iDeviceName, int iSize, ushort[] oData)
{
PlcDeviceType type;
int addr;
GetDeviceCode(iDeviceName, out type, out addr);
return ReadDeviceBlock(type, addr, iSize, oData);
}
public byte[] ReadDeviceBlock(PlcDeviceType iType, int iAddress, int iSize, ushort[] oData)
{
PlcDeviceType type = iType;
int addr = iAddress;
List data;
byte[] sdCommand;
int length;
switch (CommandFrame)
{
case McFrame.MC3E:
data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)type, (byte)iSize, (byte)(iSize >> 8) };
sdCommand = Command.SetCommandMC3E(0x0401, 0x0000, data.ToArray());
length = 11;
break;
case McFrame.MC4E:
data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)type, (byte)iSize, (byte)(iSize >> 8) };
sdCommand = Command.SetCommandMC4E(0x0401, 0x0000, data.ToArray());
length = 15;
break;
case McFrame.MC1E:
data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)(addr >> 24), 0x20, 0x44, (byte)iSize, 0x00 };
sdCommand = Command.SetCommandMC1E(0x01, data.ToArray());
length = 2;
break;
default:
throw new Exception("Message frame not supported");
}
byte[] rtResponse = TryExecution(sdCommand, length);
int rtCode = Command.SetResponse(rtResponse);
byte[] rtData = Command.Response;
for (int i = 0; i < iSize; ++i)
{
if (rtCode == 0)
{
oData[i] = (ushort)(rtData[i * 2] << 8 | rtData[i * 2 + 1]);
}
//oData[i] = (rtCode == 0) ? BitConverter.ToUInt16(rtData, i * 2) : 0;
}
return rtData;
}
public int SetDevice(string iDeviceName, int iData)
{
PlcDeviceType type;
int addr;
GetDeviceCode(iDeviceName, out type, out addr);
return SetDevice(type, addr, iData);
}
public int SetDevice(PlcDeviceType iType, int iAddress, int iData)
{
PlcDeviceType type = iType;
int addr = iAddress;
var data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)type, 0x01, 0x00, (byte)iData, (byte)(iData >> 8) };
byte[] sdCommand = Command.SetCommandMC3E(0x1401, 0x0000, data.ToArray());
int length = (Command.FrameType == McFrame.MC3E) ? 11 : 15;
byte[] rtResponse = TryExecution(sdCommand, length);
int rtCode = Command.SetResponse(rtResponse);
return rtCode;
}
public int GetDevice(string iDeviceName)
{
PlcDeviceType type;
int addr;
GetDeviceCode(iDeviceName, out type, out addr);
return GetDevice(type, addr);
}
public int GetDevice(PlcDeviceType iType, int iAddress)
{
PlcDeviceType type = iType;
int addr = iAddress;
var data = new List(6) { (byte)addr, (byte)(addr >> 8), (byte)(addr >> 16), (byte)type, 0x01, 0x00 };
byte[] sdCommand = Command.SetCommandMC3E(0x0401, 0x0000, data.ToArray());
int length = (Command.FrameType == McFrame.MC3E) ? 11 : 15;
byte[] rtResponse = TryExecution(sdCommand, length);
int rtCode = Command.SetResponse(rtResponse);
if (0 < rtCode)
{
this.Device = 0;
}
else
{
byte[] rtData = Command.Response;
this.Device = BitConverter.ToInt16(rtData, 0);
}
return rtCode;
}
#region IPlcEx
///
/// 得到字节数据
///
/// 如:M1000
/// 读取长度:>0
/// 数据
public int[] GetBitDevice(string iDeviceName, int iSize = 1)
{
int[] oData = new int[iSize];
GetBitDevice(iDeviceName, iSize, oData);
return oData;
}
///
/// 得到字节数据
///
/// 设备类型,如:M
/// 如:M1000
/// 读取长度:>0
/// 数据
public int[] GetBitDevice(PlcDeviceType iType, int iAddress, int iSize = 1)
{
int[] oData = new int[iSize];
GetBitDevice(iType, iAddress, iSize, oData);
return oData;
}
///
/// 设置字节数据
///
/// 如:M1000
/// 设置的数据
public void SetBitDevice(string iDeviceName, params int[] iData)
{
SetBitDevice(iDeviceName, iData.Length, iData);
}
///
/// 设置字节数据
///
/// 设备类型,如:M
/// 如:M1000
/// 设置的数据
public void SetBitDevice(PlcDeviceType iType, int iAddress, params int[] iData)
{
SetBitDevice(iType, iAddress, iData.Length, iData);
}
///
/// 得到数据块
///
/// 如:D1000
/// 读取长度:>0
/// 数据
public ushort[] ReadDeviceBlock(string iDeviceName, int iSize = 1)
{
ushort[] oData = new ushort[iSize];
ReadDeviceBlock(iDeviceName, iSize, oData);
return oData;
}
///
/// 得到数据块
///
/// 设备类型,如:D
/// 如:D1000
/// 读取长度:>0
/// 数据
public ushort[] ReadDeviceBlock(PlcDeviceType iType, int iAddress, int iSize = 1)
{
ushort[] oData = new ushort[iSize];
ReadDeviceBlock(iType, iAddress, iSize, oData);
return oData;
}
///
/// 写入数据块
///
/// 如:D1000
/// 写入10进制数据
public void WriteDeviceBlock(string iDeviceName, params ushort[] iData)
{
WriteDeviceBlock(iDeviceName, iData.Length, iData);
}
///
/// 写入数据块
///
/// 设备类型,如:D
/// 如:D1000
/// 写入10进制数据
public void WriteDeviceBlock(PlcDeviceType iType, int iAddress, params ushort[] iData)
{
WriteDeviceBlock(iType, iAddress, iData.Length, iData);
}
#endregion
//public int GetCpuType(out string oCpuName, out int oCpuType)
//{
// int rtCode = Command.Execute(0x0101, 0x0000, new byte[0]);
// oCpuName = "dummy";
// oCpuType = 0;
// return rtCode;
//}
public PlcDeviceType GetDeviceType(string s)
{
return (s == "M") ? PlcDeviceType.M :
(s == "SM") ? PlcDeviceType.SM :
(s == "L") ? PlcDeviceType.L :
(s == "F") ? PlcDeviceType.F :
(s == "V") ? PlcDeviceType.V :
(s == "S") ? PlcDeviceType.S :
(s == "X") ? PlcDeviceType.X :
(s == "Y") ? PlcDeviceType.Y :
(s == "B") ? PlcDeviceType.B :
(s == "SB") ? PlcDeviceType.SB :
(s == "DX") ? PlcDeviceType.DX :
(s == "DY") ? PlcDeviceType.DY :
(s == "D") ? PlcDeviceType.D :
(s == "SD") ? PlcDeviceType.SD :
(s == "R") ? PlcDeviceType.R :
(s == "ZR") ? PlcDeviceType.ZR :
(s == "W") ? PlcDeviceType.W :
(s == "SW") ? PlcDeviceType.SW :
(s == "TC") ? PlcDeviceType.TC :
(s == "TS") ? PlcDeviceType.TS :
(s == "TN") ? PlcDeviceType.TN :
(s == "CC") ? PlcDeviceType.CC :
(s == "CS") ? PlcDeviceType.CS :
(s == "CN") ? PlcDeviceType.CN :
(s == "SC") ? PlcDeviceType.SC :
(s == "SS") ? PlcDeviceType.SS :
(s == "SN") ? PlcDeviceType.SN :
(s == "Z") ? PlcDeviceType.Z :
(s == "TT") ? PlcDeviceType.TT :
(s == "TM") ? PlcDeviceType.TM :
(s == "CT") ? PlcDeviceType.CT :
(s == "CM") ? PlcDeviceType.CM :
(s == "A") ? PlcDeviceType.A :
PlcDeviceType.Max;
}
public static bool IsBitDevice(PlcDeviceType type)
{
return !((type == PlcDeviceType.D) || (type == PlcDeviceType.SD) || (type == PlcDeviceType.Z) || (type == PlcDeviceType.ZR) || (type == PlcDeviceType.R) || (type == PlcDeviceType.W));
}
public bool IsHexDevice(PlcDeviceType type)
{
return (type == PlcDeviceType.X) || (type == PlcDeviceType.Y) || (type == PlcDeviceType.B) || (type == PlcDeviceType.W);
}
public void GetDeviceCode(string iDeviceName, out PlcDeviceType oType, out int oAddress)
{
string s = iDeviceName.ToUpper();
string strAddress;
// 1.取出一个字符
string strType = s.Substring(0, 1);
switch (strType)
{
case "A":
case "B":
case "D":
case "F":
case "L":
case "M":
case "R":
case "V":
case "W":
case "X":
case "Y":
// 2字母后面,它应该是一个数字,所以转换它
strAddress = s.Substring(1);
break;
case "Z":
// 再拿出一个字符
strType = s.Substring(0, 2);
// 对于文件寄存器 : 2
// 对于索引寄存器 : 1
strAddress = s.Substring(strType.Equals("ZR") ? 2 : 1);
break;
case "C":
// 再拿出一个字符
strType = s.Substring(0, 2);
switch (strType)
{
case "CC":
case "CM":
case "CN":
case "CS":
case "CT":
strAddress = s.Substring(2);
break;
default:
throw new Exception("Invalid format.");
}
break;
case "S":
// 再拿出一个字符
strType = s.Substring(0, 2);
switch (strType)
{
case "SD":
case "SM":
strAddress = s.Substring(2);
break;
default:
throw new Exception("Invalid format.");
}
break;
case "T":
// 再拿出一个字符
strType = s.Substring(0, 2);
switch (strType)
{
case "TC":
case "TM":
case "TN":
case "TS":
case "TT":
strAddress = s.Substring(2);
break;
default:
throw new Exception("Invalid format.");
}
break;
default:
throw new Exception("Invalid format.");
}
oType = GetDeviceType(strType);
oAddress = IsHexDevice(oType) ? Convert.ToInt32(strAddress, BlockSize) : Convert.ToInt32(strAddress);
}
private byte[] TryExecution(byte[] iCommand, int minlength)
{
byte[] rtResponse;
int tCount = 10;
do
{
rtResponse = Execute(iCommand);
--tCount;
if (tCount < 0)
{
throw new Exception("无法从 PLC 获取正确的值.");
}
} while (Command.IsIncorrectResponse(rtResponse, minlength));
return rtResponse;
}
// 表示用于通信的命令的内部类
class McCommand
{
public McFrame FrameType { get; private set; } // 框架类型
private uint SerialNumber { get; set; } // 序号
private uint NetworkNumber { get; set; } // 网络号码
private uint PcNumber { get; set; } // 电脑号码
private uint IoNumber { get; set; } // 请求单元 I/O 编号/O番号
private uint ChannelNumber { get; set; } // 请求单位站号
private uint CpuTimer { get; set; } // 中央处理器监控计时器
private int ResultCode { get; set; } // 退出代码
public byte[] Response { get; private set; } // 响应数据
// 构造 函数
public McCommand(McFrame iFrame)
{
FrameType = iFrame;
SerialNumber = 0x0001u;
NetworkNumber = 0x0000u;
PcNumber = 0x00FFu;
IoNumber = 0x03FFu;
ChannelNumber = 0x0000u;
CpuTimer = 0x0010u;
}
public byte[] SetCommandMC1E(byte Subheader, byte[] iData)
{
List ret = new List(iData.Length + 4);
ret.Add(Subheader);
ret.Add((byte)this.PcNumber);
ret.Add((byte)CpuTimer);
ret.Add((byte)(CpuTimer >> 8));
ret.AddRange(iData);
return ret.ToArray();
}
public byte[] SetCommandMC3E(uint iMainCommand, uint iSubCommand, byte[] iData)
{
var dataLength = (uint)(iData.Length + 6);
List ret = new List(iData.Length + 20);
uint frame = 0x0050u;
ret.Add((byte)frame);
ret.Add((byte)(frame >> 8));
ret.Add((byte)NetworkNumber);
ret.Add((byte)PcNumber);
ret.Add((byte)IoNumber);
ret.Add((byte)(IoNumber >> 8));
ret.Add((byte)ChannelNumber);
ret.Add((byte)dataLength);
ret.Add((byte)(dataLength >> 8));
ret.Add((byte)CpuTimer);
ret.Add((byte)(CpuTimer >> 8));
ret.Add((byte)iMainCommand);
ret.Add((byte)(iMainCommand >> 8));
ret.Add((byte)iSubCommand);
ret.Add((byte)(iSubCommand >> 8));
ret.AddRange(iData);
return ret.ToArray();
}
public byte[] SetCommandMC4E(uint iMainCommand, uint iSubCommand, byte[] iData)
{
var dataLength = (uint)(iData.Length + 6);
var ret = new List(iData.Length + 20);
uint frame = 0x0054u;
ret.Add((byte)frame);
ret.Add((byte)(frame >> 8));
ret.Add((byte)SerialNumber);
ret.Add((byte)(SerialNumber >> 8));
ret.Add(0x00);
ret.Add(0x00);
ret.Add((byte)NetworkNumber);
ret.Add((byte)PcNumber);
ret.Add((byte)IoNumber);
ret.Add((byte)(IoNumber >> 8));
ret.Add((byte)ChannelNumber);
ret.Add((byte)dataLength);
ret.Add((byte)(dataLength >> 8));
ret.Add((byte)CpuTimer);
ret.Add((byte)(CpuTimer >> 8));
ret.Add((byte)iMainCommand);
ret.Add((byte)(iMainCommand >> 8));
ret.Add((byte)iSubCommand);
ret.Add((byte)(iSubCommand >> 8));
ret.AddRange(iData);
return ret.ToArray();
}
public int SetResponse(byte[] iResponse)
{
int min;
switch (FrameType)
{
case McFrame.MC1E:
min = 2;
if (min <= iResponse.Length)
{
ResultCode = (int)iResponse[min - 2];
Response = new byte[iResponse.Length - 2];
Buffer.BlockCopy(iResponse, min, Response, 0, Response.Length);
}
break;
case McFrame.MC3E:
min = 11;
if (min <= iResponse.Length)
{
var btCount = new[] { iResponse[min - 4], iResponse[min - 3] };
var btCode = new[] { iResponse[min - 2], iResponse[min - 1] };
int rsCount = BitConverter.ToUInt16(btCount, 0);
ResultCode = BitConverter.ToUInt16(btCode, 0);
Response = new byte[rsCount - 2];
Buffer.BlockCopy(iResponse, min, Response, 0, Response.Length);
}
break;
case McFrame.MC4E:
min = 15;
if (min <= iResponse.Length)
{
var btCount = new[] { iResponse[min - 4], iResponse[min - 3] };
var btCode = new[] { iResponse[min - 2], iResponse[min - 1] };
int rsCount = BitConverter.ToUInt16(btCount, 0);
ResultCode = BitConverter.ToUInt16(btCode, 0);
Response = new byte[rsCount - 2];
Buffer.BlockCopy(iResponse, min, Response, 0, Response.Length);
}
break;
default:
throw new Exception("Frame type not supported.");
}
return ResultCode;
}
public bool IsIncorrectResponse(byte[] iResponse, int minLenght)
{
//TEST add 1E frame
switch (this.FrameType)
{
case McFrame.MC1E: return ((iResponse.Length < minLenght));
case McFrame.MC3E:
case McFrame.MC4E:
var btCount = new[] { iResponse[minLenght - 4], iResponse[minLenght - 3] };
var btCode = new[] { iResponse[minLenght - 2], iResponse[minLenght - 1] };
var rsCount = BitConverter.ToUInt16(btCount, 0) - 2;
var rsCode = BitConverter.ToUInt16(btCode, 0);
return (rsCode == 0 && rsCount != (iResponse.Length - minLenght));
default: throw new Exception("Type Not supported");
}
}
}
private readonly object balanceLock = new object();
protected byte[] Execute(byte[] iCommand)
{
lock (balanceLock)
{
List list = new List();
NetworkStream ns = Stream;
ns.Write(iCommand, 0, iCommand.Length);
ns.Flush();
using (var ms = new MemoryStream())
{
var buff = new byte[256];
do
{
int sz = ns.Read(buff, 0, buff.Length);
if (sz == 0)
{
throw new Exception("已断开连接");
}
ms.Write(buff, 0, sz);
}
while (ns.DataAvailable);
return ms.ToArray();
}
}
}
#region INT16
public short ReadInt16(string address)
{
try
{
return ReadInt16(address, 1)[0];
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public short[] ReadInt16(string address, int count = 1)
{
try
{
//地址解析
ushort[] value = ReadDeviceBlock(address, count);//一个地址2个字节
short[] values = new short[count];
for (int i = 0; i < count; i++)
{
byte[] data = BitConverter.GetBytes(value[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
values[i] = BitConverter.ToInt16(data, 0);
}
return values;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteInt16(string address, short value)
{
try
{
WriteInt16(address, new short[] { value });
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteInt16(string address, short[] value)
{
try
{
ushort[] values = new ushort[value.Length];
for (int i = 0; i < value.Length; i++)
{
byte[] data = BitConverter.GetBytes(value[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
values[i] = BitConverter.ToUInt16(data, 0);
}
WriteDeviceBlock(address, values);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
#region UINT16
public ushort ReadUInt16(string address)
{
try
{
return ReadUInt16(address, 1)[0];
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public ushort[] ReadUInt16(string address, int count = 1)
{
try
{
//地址解析
ushort[] value = ReadDeviceBlock(address, count);//一个地址2个字节
ushort[] values = new ushort[count];
for (int i = 0; i < count; i++)
{
byte[] data = BitConverter.GetBytes(value[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
values[i] = BitConverter.ToUInt16(data, 0);
}
return values;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteUInt16(string address, ushort value)
{
try
{
WriteUInt16(address, new ushort[] { value });
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteUInt16(string address, ushort[] value)
{
try
{
ushort[] values = new ushort[value.Length];
for (int i = 0; i < value.Length; i++)
{
byte[] data = BitConverter.GetBytes(value[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
values[i] = BitConverter.ToUInt16(data, 0);
}
WriteDeviceBlock(address, values);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
#region INT32
public int ReadInt32(string address)
{
try
{
return ReadInt32(address, 1)[0];
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public int[] ReadInt32(string address, int count = 1)
{
try
{
//地址解析
ushort[] value = ReadDeviceBlock(address, count * 2);//一个地址2个字节
int[] values = new int[count];
for (int i = 0; i < count; i++)
{
byte[] data1 = BitConverter.GetBytes(value[2 * i + 0]);
byte[] data2 = BitConverter.GetBytes(value[2 * i + 1]);
List list = new List();
list.AddRange(data1);
list.AddRange(data2);
byte[] data = list.ToArray();
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
values[i] = BitConverter.ToInt32(data, 0);
}
return values;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteInt32(string address, int value)
{
try
{
WriteInt32(address, new int[] { value });
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteInt32(string address, int[] value)
{
try
{
List values = new List();
for (int i = 0; i < value.Length; i++)
{
byte[] data = BitConverter.GetBytes(value[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
ushort value1 = BitConverter.ToUInt16(data, 0);
ushort value2 = BitConverter.ToUInt16(data, 2);
values.Add(value1);
values.Add(value2);
}
WriteDeviceBlock(address, values.ToArray());
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
#region UINT32
public uint ReadUInt32(string address)
{
try
{
return ReadUInt32(address, 1)[0];
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public uint[] ReadUInt32(string address, int count = 1)
{
try
{
//地址解析
ushort[] value = ReadDeviceBlock(address, count * 2);//一个地址2个字节
uint[] values = new uint[count];
for (int i = 0; i < count; i++)
{
byte[] data1 = BitConverter.GetBytes(value[2 * i + 0]);
byte[] data2 = BitConverter.GetBytes(value[2 * i + 1]);
List list = new List();
list.AddRange(data1);
list.AddRange(data2);
byte[] data = list.ToArray();
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
values[i] = BitConverter.ToUInt32(data, 0);
}
return values;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteUInt32(string address, uint value)
{
try
{
WriteUInt32(address, new uint[] { value });
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteUInt32(string address, uint[] value)
{
try
{
List values = new List();
for (int i = 0; i < value.Length; i++)
{
byte[] data = BitConverter.GetBytes(value[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
ushort value1 = BitConverter.ToUInt16(data, 0);
ushort value2 = BitConverter.ToUInt16(data, 2);
values.Add(value1);
values.Add(value2);
}
WriteDeviceBlock(address, values.ToArray());
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
#region FLOAT
public float ReadFloat(string address)
{
try
{
return ReadFloat(address, 1)[0];
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public float[] ReadFloat(string address, int count = 1)
{
try
{
//地址解析
ushort[] value = ReadDeviceBlock(address, count * 2);//一个地址2个字节
float[] values = new float[count];
for (int i = 0; i < count; i++)
{
byte[] data1 = BitConverter.GetBytes(value[2 * i + 0]);
byte[] data2 = BitConverter.GetBytes(value[2 * i + 1]);
List list = new List();
list.AddRange(data1);
list.AddRange(data2);
byte[] data = list.ToArray();
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
values[i] = BitConverter.ToSingle(data, 0);
}
return values;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteFloat(string address, float value)
{
try
{
WriteFloat(address, new float[] { value });
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteFloat(string address, float[] value)
{
try
{
List values = new List();
for (int i = 0; i < value.Length; i++)
{
byte[] data = BitConverter.GetBytes(value[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
ushort value1 = BitConverter.ToUInt16(data, 0);
ushort value2 = BitConverter.ToUInt16(data, 2);
values.Add(value1);
values.Add(value2);
}
WriteDeviceBlock(address, values.ToArray());
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
#region Double
public double ReadDouble(string address)
{
try
{
return ReadDouble(address, 1)[0];
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public double[] ReadDouble(string address, int count = 1)
{
try
{
//地址解析
ushort[] value = ReadDeviceBlock(address, count * 4);
double[] values = new double[count];
for (int i = 0; i < count; i++)
{
byte[] data1 = BitConverter.GetBytes(value[4 * i + 0]);
byte[] data2 = BitConverter.GetBytes(value[4 * i + 1]);
byte[] data3 = BitConverter.GetBytes(value[4 * i + 2]);
byte[] data4 = BitConverter.GetBytes(value[4 * i + 3]);
List list = new List();
list.AddRange(data1);
list.AddRange(data2);
list.AddRange(data3);
list.AddRange(data4);
byte[] data = list.ToArray();
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
values[i] = BitConverter.ToDouble(data, 0);
}
return values;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteDouble(string address, double value)
{
try
{
WriteDouble(address, new double[] { value });
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteDouble(string address, double[] value)
{
try
{
List values = new List();
for (int i = 0; i < value.Length; i++)
{
byte[] data = BitConverter.GetBytes(value[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
ushort value1 = BitConverter.ToUInt16(data, 0);
ushort value2 = BitConverter.ToUInt16(data, 2);
ushort value3 = BitConverter.ToUInt16(data, 4);
ushort value4 = BitConverter.ToUInt16(data, 6);
values.Add(value1);
values.Add(value2);
values.Add(value3);
values.Add(value4);
}
WriteDeviceBlock(address, values.ToArray());
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
#region Int64
public long ReadInt64(string address)
{
try
{
return ReadInt64(address, 1)[0];
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public long[] ReadInt64(string address, int count = 1)
{
try
{
//地址解析
ushort[] value = ReadDeviceBlock(address, count * 4);
long[] values = new long[count];
for (int i = 0; i < count; i++)
{
byte[] data1 = BitConverter.GetBytes(value[4 * i + 0]);
byte[] data2 = BitConverter.GetBytes(value[4 * i + 1]);
byte[] data3 = BitConverter.GetBytes(value[4 * i + 2]);
byte[] data4 = BitConverter.GetBytes(value[4 * i + 3]);
List list = new List();
list.AddRange(data1);
list.AddRange(data2);
list.AddRange(data3);
list.AddRange(data4);
byte[] data = list.ToArray();
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
values[i] = BitConverter.ToInt64(data, 0);
}
return values;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteInt64(string address, long value)
{
try
{
WriteInt64(address, new long[] { value });
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
public void WriteInt64(string address, long[] value)
{
try
{
List values = new List();
for (int i = 0; i < value.Length; i++)
{
byte[] data = BitConverter.GetBytes(value[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(data);
}
ushort value1 = BitConverter.ToUInt16(data, 0);
ushort value2 = BitConverter.ToUInt16(data, 2);
ushort value3 = BitConverter.ToUInt16(data, 4);
ushort value4 = BitConverter.ToUInt16(data, 6);
values.Add(value1);
values.Add(value2);
values.Add(value3);
values.Add(value4);
}
WriteDeviceBlock(address, values.ToArray());
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
#endregion
}
public enum McFrame
{
MC1E = 4,
MC3E = 11,
MC4E = 15
}
///
/// 定义 PLC 设备类型的枚举
///
public enum PlcDeviceType
{
// PLC设备
M = 0x90
, SM = 0x91
, L = 0x92
, F = 0x93
, V = 0x94
, S = 0x98
, X = 0x9C
, Y = 0x9D
, B = 0xA0
, SB = 0xA1
, DX = 0xA2
, DY = 0xA3
, D = 0xA8
, SD = 0xA9
, R = 0xAF
, ZR = 0xB0
, W = 0xB4
, SW = 0xB5
, TC = 0xC0
, TS = 0xC1
, TN = 0xC2
, CC = 0xC3
, CS = 0xC4
, CN = 0xC5
, SC = 0xC6
, SS = 0xC7
, SN = 0xC8
, Z = 0xCC
, TT
, TM
, CT
, CM
, A
, Max
}
}