Files
DevToolsAvalonia/常用工具集/Utility/Network/Mitsubishi/McProtocolTcp.cs
2025-08-26 08:37:44 +08:00

1392 lines
47 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
{
/// <summary>
/// 使用的指令框架
/// </summary>
public McFrame CommandFrame { get; set; }
private McCommand Command { get; set; }
/// <summary>
/// 主机名或者IP地址
/// </summary>
public string HostName { get; set; }
/// <summary>
/// 端口号
/// </summary>
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;
}
}
/// <summary>
/// 构造函数
/// </summary>
public McProtocolTcp() : this("", 0, McFrame.MC3E)
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="iHostName"></param>
/// <param name="iPortNumber"></param>
/// <param name="frame"></param>
public McProtocolTcp(string iHostName, int iPortNumber, McFrame frame)
{
CommandFrame = frame;
Client = new TcpClient();
//C70 = MC3E
HostName = iHostName;
PortNumber = iPortNumber;
}
/// <summary>
/// 后处理
/// </summary>
public void Dispose()
{
TcpClient c = Client;
if (c.Connected)
{
c.Close();
}
}
public void Open()
{
if (!Client.Connected)
{
// 实现Keep Alive功能
var ka = new List<byte>(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<byte>(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<byte>(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<byte> data;
List<byte> DeviceData = new List<byte>();
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<byte>(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<byte>(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<byte>(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<byte> data;
byte[] sdCommand;
int length;
switch (CommandFrame)
{
case McFrame.MC3E:
data = new List<byte>(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<byte>(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<byte>(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<byte>(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<byte>(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
/// <summary>
/// 得到字节数据
/// </summary>
/// <param name="iDeviceName">如M1000</param>
/// <param name="iSize">读取长度:>0</param>
/// <returns>数据</returns>
public int[] GetBitDevice(string iDeviceName, int iSize = 1)
{
int[] oData = new int[iSize];
GetBitDevice(iDeviceName, iSize, oData);
return oData;
}
/// <summary>
/// 得到字节数据
/// </summary>
/// <param name="iType">设备类型M</param>
/// <param name="iAddress">如M1000</param>
/// <param name="iSize">读取长度:>0</param>
/// <returns>数据</returns>
public int[] GetBitDevice(PlcDeviceType iType, int iAddress, int iSize = 1)
{
int[] oData = new int[iSize];
GetBitDevice(iType, iAddress, iSize, oData);
return oData;
}
/// <summary>
/// 设置字节数据
/// </summary>
/// <param name="iDeviceName">如M1000</param>
/// <param name="iData">设置的数据</param>
public void SetBitDevice(string iDeviceName, params int[] iData)
{
SetBitDevice(iDeviceName, iData.Length, iData);
}
/// <summary>
/// 设置字节数据
/// </summary>
/// <param name="iType">设备类型M</param>
/// <param name="iAddress">如M1000</param>
/// <param name="iData">设置的数据</param>
public void SetBitDevice(PlcDeviceType iType, int iAddress, params int[] iData)
{
SetBitDevice(iType, iAddress, iData.Length, iData);
}
/// <summary>
/// 得到数据块
/// </summary>
/// <param name="iDeviceName">如D1000</param>
/// <param name="iSize">读取长度:>0</param>
/// <returns>数据</returns>
public ushort[] ReadDeviceBlock(string iDeviceName, int iSize = 1)
{
ushort[] oData = new ushort[iSize];
ReadDeviceBlock(iDeviceName, iSize, oData);
return oData;
}
/// <summary>
/// 得到数据块
/// </summary>
/// <param name="iType">设备类型D</param>
/// <param name="iAddress">如D1000</param>
/// <param name="iSize">读取长度:>0</param>
/// <returns>数据</returns>
public ushort[] ReadDeviceBlock(PlcDeviceType iType, int iAddress, int iSize = 1)
{
ushort[] oData = new ushort[iSize];
ReadDeviceBlock(iType, iAddress, iSize, oData);
return oData;
}
/// <summary>
/// 写入数据块
/// </summary>
/// <param name="iDeviceName">如D1000</param>
/// <param name="iData">写入10进制数据</param>
public void WriteDeviceBlock(string iDeviceName, params ushort[] iData)
{
WriteDeviceBlock(iDeviceName, iData.Length, iData);
}
/// <summary>
/// 写入数据块
/// </summary>
/// <param name="iType">设备类型D</param>
/// <param name="iAddress">如D1000</param>
/// <param name="iData">写入10进制数据</param>
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<byte> ret = new List<byte>(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<byte> ret = new List<byte>(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<byte>(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<byte> list = new List<byte>();
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<byte> list = new List<byte>();
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<ushort> values = new List<ushort>();
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<byte> list = new List<byte>();
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<ushort> values = new List<ushort>();
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<byte> list = new List<byte>();
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<ushort> values = new List<ushort>();
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<byte> list = new List<byte>();
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<ushort> values = new List<ushort>();
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<byte> list = new List<byte>();
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<ushort> values = new List<ushort>();
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
}
/// <summary>
/// 定义 PLC 设备类型的枚举
/// </summary>
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
}
}