diff --git a/SCADA/Program/DataExchange.sln b/SCADA/Program/DataExchange.sln
index 492bf4f..3a0ccad 100644
--- a/SCADA/Program/DataExchange.sln
+++ b/SCADA/Program/DataExchange.sln
@@ -33,6 +33,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TagConfig", "TagConfig\TagC
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PanasonicDriver", "PanasonicDriver\PanasonicDriver.csproj", "{0D1C943D-594F-4E07-AA39-90CEC4E37C8E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OmronPlcDriver", "OmronPlcDriver\OmronPlcDriver.csproj", "{BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -299,6 +301,26 @@ Global
{0D1C943D-594F-4E07-AA39-90CEC4E37C8E}.Release|x64.Build.0 = Release|Any CPU
{0D1C943D-594F-4E07-AA39-90CEC4E37C8E}.Release|x86.ActiveCfg = Release|Any CPU
{0D1C943D-594F-4E07-AA39-90CEC4E37C8E}.Release|x86.Build.0 = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|Itanium.ActiveCfg = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|Itanium.Build.0 = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|x64.Build.0 = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Debug|x86.Build.0 = Debug|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|Itanium.ActiveCfg = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|Itanium.Build.0 = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|x64.ActiveCfg = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|x64.Build.0 = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|x86.ActiveCfg = Release|Any CPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs b/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs
index a4f4d6f..febbb3e 100644
--- a/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs
+++ b/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs
@@ -236,49 +236,53 @@ namespace ModbusDriver
return data;
}
+ object _async = new object();
private byte[] WriteSyncData(byte[] write_data)
{
short id = BitConverter.ToInt16(write_data, 0);
if (IsClosed) CallException(id, write_data[7], Modbus.excExceptionConnectionLost);
else
{
- try
+ lock (_async)
{
- tcpSynCl.Send(write_data, 0, write_data.Length, SocketFlags.None);//是否存在lock的问题?
- int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 0xFF, SocketFlags.None);
+ try
+ {
+ tcpSynCl.Send(write_data, 0, write_data.Length, SocketFlags.None);//是否存在lock的问题?
+ int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 0xFF, SocketFlags.None);
- byte function = tcpSynClBuffer[7];
- byte[] data;
+ byte function = tcpSynClBuffer[7];
+ byte[] data;
- if (result == 0) CallException(id, write_data[7], Modbus.excExceptionConnectionLost);
+ if (result == 0) CallException(id, write_data[7], Modbus.excExceptionConnectionLost);
- // ------------------------------------------------------------
- // Response data is slave ModbusModbus.exception
- if (function > Modbus.excExceptionOffset)
- {
- function -= Modbus.excExceptionOffset;
- CallException(id, function, tcpSynClBuffer[8]);
- return null;
- }
- // ------------------------------------------------------------
- // Write response data
- else if ((function >= Modbus.fctWriteSingleCoil) && (function != Modbus.fctReadWriteMultipleRegister))
- {
- data = new byte[2];
- Array.Copy(tcpSynClBuffer, 10, data, 0, 2);
+ // ------------------------------------------------------------
+ // Response data is slave ModbusModbus.exception
+ if (function > Modbus.excExceptionOffset)
+ {
+ function -= Modbus.excExceptionOffset;
+ CallException(id, function, tcpSynClBuffer[8]);
+ return null;
+ }
+ // ------------------------------------------------------------
+ // Write response data
+ else if ((function >= Modbus.fctWriteSingleCoil) && (function != Modbus.fctReadWriteMultipleRegister))
+ {
+ data = new byte[2];
+ Array.Copy(tcpSynClBuffer, 10, data, 0, 2);
+ }
+ // ------------------------------------------------------------
+ // Read response data
+ else
+ {
+ data = new byte[tcpSynClBuffer[8]];
+ Array.Copy(tcpSynClBuffer, 9, data, 0, tcpSynClBuffer[8]);
+ }
+ return data;
}
- // ------------------------------------------------------------
- // Read response data
- else
+ catch (SocketException)
{
- data = new byte[tcpSynClBuffer[8]];
- Array.Copy(tcpSynClBuffer, 9, data, 0, tcpSynClBuffer[8]);
+ CallException(id, write_data[7], Modbus.excExceptionConnectionLost);
}
- return data;
- }
- catch (SocketException)
- {
- CallException(id, write_data[7], Modbus.excExceptionConnectionLost);
}
}
return null;
@@ -568,7 +572,7 @@ namespace ModbusDriver
byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据
if (rcvBytes == null || rcvBytes.Length == 0)
{
- offset += area.Len / 2;
+ //offset += area.Len / 2;
//_plcReader.Connect();
continue;
}
diff --git a/SCADA/Program/OmronPlcDriver/OmronPlcDriver.csproj b/SCADA/Program/OmronPlcDriver/OmronPlcDriver.csproj
new file mode 100644
index 0000000..ae3c4d3
--- /dev/null
+++ b/SCADA/Program/OmronPlcDriver/OmronPlcDriver.csproj
@@ -0,0 +1,55 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {BAF8082B-8DD8-4E7C-9C5B-D9213E08C3B1}
+ Library
+ Properties
+ OmronPlcDriver
+ OmronPlcDriver
+ v4.0
+ 512
+ Client
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+ {8965e389-6466-4b30-bd43-83c909044637}
+ DataService
+
+
+
+
+
\ No newline at end of file
diff --git a/SCADA/Program/OmronPlcDriver/OmronUdpReader.cs b/SCADA/Program/OmronPlcDriver/OmronUdpReader.cs
new file mode 100644
index 0000000..7778e61
--- /dev/null
+++ b/SCADA/Program/OmronPlcDriver/OmronUdpReader.cs
@@ -0,0 +1,875 @@
+using DataService;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Timers;
+
+namespace OmronPlcDriver
+{
+ [Description("Omron(CS/CJ) UDP协议")]
+ public sealed class OmronUdpReader : IPLCDriver, IMultiReadWrite
+ {
+ #region
+
+ /****************************************/
+ //更新人:新增_pdu,可以根据实际情况进行采集
+ //更新日期:20171205
+ //更新原因:根据现场进行参数调整以提供采集响应速度
+ /***************************************/
+ ///
+ /// PDU的值
+ ///
+ int _pdu;
+ ///
+ /// 获取PDU的值
+ ///
+ public int PDU
+ {
+ get { return _pdu; }
+ }
+ ///
+ /// 获取设备地址
+ ///
+ ///
+ ///
+ public DeviceAddress GetDeviceAddress(string address)
+ {
+ DeviceAddress dv = DeviceAddress.Empty;
+ if (string.IsNullOrEmpty(address))
+ return dv;
+ dv.Area = _plcNodeId;
+ switch (address[0])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ int index = address.IndexOf('.');
+ dv.DBNumber = OmronCSCJ.fctCIO;
+ if (index > 0)
+ {
+ dv.Start = int.Parse(address.Substring(0, index - 1));
+ dv.Bit = byte.Parse(address.Substring(index + 1));
+ }
+ else
+ dv.Start = int.Parse(address);
+ }
+ break;
+ case 'D'://DM区
+ {
+ int index = address.IndexOf('.');
+ dv.DBNumber = OmronCSCJ.fctDM;
+ if (index > 0)
+ {
+ dv.Start = int.Parse(address.Substring(1, index - 1));
+ dv.Bit = byte.Parse(address.Substring(index + 1));
+ }
+ else
+ dv.Start = int.Parse(address.Substring(index + 1));
+ }
+ break;
+ case 'H'://HR区
+ {
+ int index = address.IndexOf('.');
+ dv.DBNumber = OmronCSCJ.fctHR;
+ if (index > 0)
+ {
+ dv.Start = int.Parse(address.Substring(1, index - 1));
+ dv.Bit = byte.Parse(address.Substring(index + 1));
+ }
+ else
+ dv.Start = int.Parse(address.Substring(1));
+ }
+ break;
+ case 'A'://AR区
+ {
+ int index = address.IndexOf('.');
+ dv.DBNumber = OmronCSCJ.fctA;
+ if (index > 0)
+ {
+ dv.Start = int.Parse(address.Substring(1, index - 1));
+ dv.Bit = byte.Parse(address.Substring(index + 1));
+ }
+ else
+ dv.Start = int.Parse(address.Substring(1));
+ }
+ break;
+ }
+ return dv;
+ }
+
+ public string GetAddress(DeviceAddress address)
+ {
+ return string.Empty;
+ }
+
+ #endregion
+ private int _timeout;//超时数据
+
+ private Socket udpSynCl;
+ private byte[] udpSynClBuffer = new byte[1024];
+
+ short _id;//驱动id
+ //驱动id
+ public short ID
+ {
+ get
+ {
+ return _id;
+ }
+ }
+
+ string _name;//驱动名称
+ ///
+ /// 驱动名称
+ ///
+ public string Name
+ {
+ get
+ {
+ return _name;
+ }
+ }
+
+ string _ip;//服务ip
+ int _port = 9600; //服务端口
+ public string ServerName
+ {
+ get { return _ip + ":" + _port; }
+ set
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ int index = value.IndexOf(':');
+ _ip = value.Substring(0, index - 1);//ip地址
+ _port = int.Parse(value.Substring(index + 1));//端口号
+ }
+ }
+ }
+ ///
+ /// 是否关闭
+ ///
+ public bool IsClosed
+ {
+ get
+ {
+ return udpSynCl == null || udpSynCl.Connected == false;
+ }
+ }
+ ///
+ /// 超时时间
+ ///
+
+ public int TimeOut
+ {
+ get { return _timeout; }
+ set { _timeout = value; }
+ }
+
+ byte _plcNodeId;//plc节点号
+ ///
+ /// plc节点号,从para1参数读取
+ ///
+ public byte PlcNodeId
+ {
+ get { return _pcNodeId; }
+ set { _pcNodeId = value; }
+ }
+
+ byte _pcNodeId;//电脑节点号
+ ///
+ /// 电脑节点号,从para2参数读取
+ ///
+ public byte PcNodeId
+ {
+ get { return _pcNodeId; }
+ set { _pcNodeId = value; }
+ }
+
+ List _grps = new List(20);
+ public IEnumerable Groups
+ {
+ get { return _grps; }
+ }
+
+ IDataServer _server;
+ public IDataServer Parent
+ {
+ get { return _server; }
+ }
+
+ public OmronUdpReader(IDataServer server, short id, string name, string servername, int timeOut = 500, string spare1 = null, string spare2 = null)
+ {
+ _id = id;
+ _name = name;
+ _server = server;
+ if (!string.IsNullOrEmpty(servername))
+ {
+ int index = servername.IndexOf(':');
+ _ip = servername.Substring(0, index - 1);//ip地址
+ _port = int.Parse(servername.Substring(index + 1));//端口号
+ }
+ _timeout = timeOut;
+ byte.TryParse(spare1, out _plcNodeId);
+ byte.TryParse(spare2, out _pcNodeId);
+ }
+
+ ///
+ /// 连接
+ ///
+ ///
+ public bool Connect()
+ {
+ try
+ {
+ if (udpSynCl != null)
+ udpSynCl.Close();
+ //IPAddress ip = IPAddress.Parse(_ip);
+ // ----------------------------------------------------------------
+ // Connect synchronous client
+ udpSynCl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Udp);
+ udpSynCl.SendTimeout = _timeout;
+ udpSynCl.ReceiveTimeout = _timeout;
+ udpSynCl.NoDelay = true;
+ udpSynCl.Connect(_ip, _port);
+ return true;
+ }
+ catch (SocketException error)
+ {
+ if (OnClose != null)
+ OnClose(this, new ShutdownRequestEventArgs(error.Message));
+ return false;
+ }
+ }
+ ///
+ /// 生成读命令头
+ ///
+ /// 电脑节点号,设置和PLC节点不一致即可
+ /// 读取的起始地址
+ /// 读取长度
+ ///
+ /// PLC节点号,可为0
+ ///
+ private byte[] CreateReadHeader(byte pcnode, int startAddress, ushort length, byte function, byte plcnode = 0)
+ {
+ byte[] data = new byte[18];
+ data[0] = 0x80;
+ data[1] = 0;
+ data[2] = 0; //80 00 02 固定帧头
+ data[2] = 0;
+ data[3] = plcnode;
+ data[5] = 0; //设备的网络号,节点号,单元号
+ data[6] = 0;
+ data[7] = pcnode;
+ data[8] = 0; //PC的网络号,节点号,单元号
+ data[9] = 0;
+ data[10] = 1;
+ data[11] = 1; //SID+MRC+SRC
+ data[12] = function; //数据区代码
+ byte[] _adr = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)startAddress));
+ data[13] = _adr[0]; // 首地址高字节
+ data[14] = _adr[1]; // 首地址低字节
+ data[15] = 0; // 固定0
+ byte[] _length = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)length));
+ data[16] = _length[0]; // 读取数量高字节
+ data[17] = _length[1]; // 读取数量低字节
+ return data;
+ }
+ ///
+ /// 生成写命令头
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private byte[] CreateWriteHeader(byte pcnode, int startAddress, ushort numData, byte function, byte plcnode = 0)
+ {
+ byte[] data = new byte[numData + 18];
+ data[0] = 0x80;
+ data[1] = 0;
+ data[2] = 0; //80 00 02 固定帧头
+ data[3] = 0;
+ data[4] = plcnode;
+ data[5] = 0; //设备的网络号,节点号,单元号
+ data[6] = 0;
+ data[7] = pcnode;
+ data[8] = 0; //PC的网络号,节点号,单元号
+ data[9] = 0;
+ data[10] = 1;
+ data[11] = 2; //SID+MRC+SRC
+ data[12] = function; //数据区代码
+ byte[] _adr = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)startAddress));
+ data[13] = _adr[0]; // 首地址高字节
+ data[14] = _adr[1]; // 首地址低字节
+ data[15] = 0; // 固定0
+ byte[] length = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)numData / 2));
+ data[16] = length[0]; // 写取数量高字节
+ data[17] = length[1]; // 写取数量低字节
+ return data;
+ }
+ ///
+ /// 同步写数据到udp
+ ///
+ /// 写的字节数组
+ ///
+ private byte[] WriteSyncData(byte[] write_data)
+ {
+ short id = BitConverter.ToInt16(write_data, 4);
+ if (IsClosed) CallException(id, write_data[12], OmronCSCJ.excExceptionConnectionLost);
+ else
+ {
+ try
+ {
+ udpSynCl.Send(write_data, 0, write_data.Length, SocketFlags.None);//是否存在lock的问题?
+ int result = udpSynCl.Receive(udpSynClBuffer, 0, 1024, SocketFlags.None);
+
+ byte function = udpSynClBuffer[11];//读写功能
+ byte[] data;
+
+ int err = udpSynClBuffer[12] * 256 + udpSynClBuffer[13];
+
+ if (result == 0) CallException(id, write_data[12], OmronCSCJ.excExceptionConnectionLost);
+
+ // ------------------------------------------------------------
+ // Response data is slave ModbusModbus.exception
+ if (err != 0)
+ {
+ CallException(id, function, 4);
+ return null;
+ }
+ // ------------------------------------------------------------
+ // Write response data
+ else if (function == 0x2)
+ {
+ data = new byte[2];
+ Array.Copy(udpSynClBuffer, 10, data, 0, 2);
+ }
+ // ------------------------------------------------------------
+ // Read response data
+ else
+ {
+ data = new byte[(write_data[16] * 256 + write_data[17]) * 2];
+ Array.Copy(udpSynClBuffer, 14, data, 0, data.Length);
+ }
+ return data;
+ }
+ catch (SocketException)
+ {
+ CallException(id, write_data[12], OmronCSCJ.excExceptionConnectionLost);
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// 写单个寄存器
+ ///
+ /// 电脑节点号
+ /// 起始地址
+ /// 内存区功能吗
+ /// 写值数组
+ /// plc节点号
+ ///
+ public byte[] WriteSingleRegister(byte pcnode, int startAddress, byte function, byte[] values, byte plcnode = 0)
+ {
+ byte[] data;
+ data = CreateWriteHeader(pcnode, startAddress, 2, function, plcnode);
+ data[19] = values[0];
+ data[20] = values[1];
+ return WriteSyncData(data);
+ }
+ ///
+ /// 写多个寄存器
+ ///
+ /// 电脑节点号
+ /// 起始地址
+ /// 内存区功能号
+ /// 写值数组
+ /// plc节点号
+ ///
+ public byte[] WriteMultipleRegister(byte pcnode, int startAddress, byte function, byte[] values, byte plcnode = 0)
+ {
+ ushort numBytes = Convert.ToUInt16(values.Length);
+ if (numBytes % 2 > 0) numBytes++;
+ byte[] data;
+
+ data = CreateWriteHeader(pcnode, startAddress, numBytes, function, plcnode);
+ Array.Copy(values, 0, data, 19, values.Length);
+ return WriteSyncData(data);
+ }
+
+ public IGroup AddGroup(string name, short id, int updateRate, float deadBand = 0f, bool active = false)
+ {
+ OmronUdpGroup grp = new OmronUdpGroup(id, name, updateRate, active, this);
+ _grps.Add(grp);
+ return grp;
+ }
+
+ public bool RemoveGroup(IGroup grp)
+ {
+ grp.IsActive = false;
+ return _grps.Remove(grp);
+ }
+
+ public void Dispose()
+ {
+ if (udpSynCl != null)
+ {
+ try { udpSynCl.Shutdown(SocketShutdown.Both); }
+ catch { }
+ udpSynCl.Close();
+
+ udpSynCl = null;
+ }
+ foreach (IGroup grp in _grps)
+ {
+ grp.Dispose();
+ }
+ _grps.Clear();
+ }
+
+ internal string GetErrorString(byte exception)
+ {
+ switch (exception)
+ {
+ case OmronCSCJ.excIllegalFunction:
+ return "Constant for OmronCSCJ.exception illegal function.";
+ case OmronCSCJ.excIllegalDataAdr:
+ return "Constant for OmronCSCJ.exception illegal data address.";
+ case OmronCSCJ.excIllegalDataVal:
+ return "Constant for OmronCSCJ.exception illegal data value.";
+ case OmronCSCJ.excSlaveDeviceFailure:
+ return "Constant for OmronCSCJ.exception slave device failure.";
+ case OmronCSCJ.excAck:
+ return "Constant for OmronCSCJ.exception acknowledge.";
+ case OmronCSCJ.excSlaveIsBusy:
+ return "Constant for OmronCSCJ.exception slave is busy/booting up.";
+ case OmronCSCJ.excGatePathUnavailable:
+ return "Constant for OmronCSCJ.exception gate path unavailable.";
+ case OmronCSCJ.excExceptionNotConnected:
+ return "Constant for OmronCSCJ.exception not connected.";
+ case OmronCSCJ.excExceptionConnectionLost:
+ return "Constant for OmronCSCJ.exception connection lost.";
+ case OmronCSCJ.excExceptionTimeout:
+ return "Constant for OmronCSCJ.exception response timeout.";
+ case OmronCSCJ.excExceptionOffset:
+ return "Constant for OmronCSCJ.exception wrong offset.";
+ case OmronCSCJ.excSendFailt:
+ return "Constant for OmronCSCJ.exception send failt.";
+ }
+ return string.Empty;
+ }
+
+ internal void CallException(int id, byte function, byte exception)
+ {
+ if (udpSynCl == null) return;
+ if (exception == OmronCSCJ.excExceptionConnectionLost && IsClosed == false)
+ {
+ if (OnClose != null)
+ OnClose(this, new ShutdownRequestEventArgs(GetErrorString(exception)));
+ }
+ }
+
+ ///
+ /// 读取字节数组
+ ///
+ /// 标签变量地址结构
+ /// 长度
+ ///
+ public byte[] ReadBytes(DeviceAddress address, ushort size)
+ {
+ ushort len = size;
+ if (len % 2 != 0)
+ {
+ len++;
+ }
+ return WriteSyncData(CreateReadHeader(PcNodeId, address.Start, (ushort)(len / 2), (byte)address.DBNumber, (byte)address.Area));
+ }
+ ///
+ /// 读取32位整数
+ ///
+ /// 标签变量地址结构
+ ///
+ public ItemData ReadInt32(DeviceAddress address)
+ {
+ byte[] data = WriteSyncData(CreateReadHeader(PcNodeId, address.Start, 2, (byte)address.DBNumber, (byte)address.Area));
+ if (data == null)
+ return new ItemData(0, 0, QUALITIES.QUALITY_BAD);
+ else
+ return new ItemData(IPAddress.HostToNetworkOrder(BitConverter.ToInt32(data, 0)), 0, QUALITIES.QUALITY_GOOD);
+ }
+ ///
+ /// 读取16位整数
+ ///
+ /// 标签变量地址结构
+ ///
+ public ItemData ReadInt16(DeviceAddress address)
+ {
+ byte[] data = WriteSyncData(CreateReadHeader(PcNodeId, address.Start, 1, (byte)address.DBNumber, (byte)address.Area));
+ if (data == null)
+ return new ItemData(0, 0, QUALITIES.QUALITY_BAD);
+ else
+ return new ItemData(IPAddress.HostToNetworkOrder(BitConverter.ToInt16(data, 0)), 0, QUALITIES.QUALITY_GOOD);
+ }
+ ///
+ /// 读取1字节
+ ///
+ /// 标签变量地址结构
+ ///
+ public ItemData ReadByte(DeviceAddress address)
+ {
+ byte[] data = WriteSyncData(CreateReadHeader(PcNodeId, address.Start, 1, (byte)address.DBNumber, (byte)address.Area));
+ if (data == null)
+ return new ItemData(0, 0, QUALITIES.QUALITY_BAD);
+ else
+ return new ItemData(data[0], 0, QUALITIES.QUALITY_GOOD);
+ }
+ ///
+ /// 读取字符串
+ ///
+ /// 标签变量地址结构
+ /// 长度
+ ///
+ public ItemData ReadString(DeviceAddress address, ushort size)
+ {
+ byte[] data = WriteSyncData(CreateReadHeader(PcNodeId, address.Start, size, (byte)address.DBNumber, (byte)address.Area));
+ if (data == null)
+ return new ItemData(string.Empty, 0, QUALITIES.QUALITY_BAD);
+ else
+ return new ItemData(Encoding.ASCII.GetString(data, 0, data.Length), 0, QUALITIES.QUALITY_GOOD);//是否考虑字节序问题?
+ }
+ ///
+ /// 读取32位浮点数
+ ///
+ /// 标签变量地址结构
+ ///
+ public unsafe ItemData ReadFloat(DeviceAddress address)
+ {
+ byte[] data = WriteSyncData(CreateReadHeader(PcNodeId, address.Start, 2, (byte)address.DBNumber, (byte)address.Area));
+ if (data == null)
+ return new ItemData(0.0f, 0, QUALITIES.QUALITY_BAD);
+ else
+ {
+ int value = IPAddress.HostToNetworkOrder(BitConverter.ToInt32(data, 0));
+ return new ItemData(*(((float*)&value)), 0, QUALITIES.QUALITY_GOOD);
+ }
+ }
+ ///
+ /// 读取1位
+ ///
+ /// 标签变量地址结构体
+ ///
+ public ItemData ReadBit(DeviceAddress address)
+ {
+ byte[] data = WriteSyncData(CreateReadHeader(PcNodeId, address.Start, 1, (byte)address.DBNumber, (byte)address.Area));
+ if (data == null)
+ return new ItemData(false, 0, QUALITIES.QUALITY_BAD);
+ if (data.Length == 1) return new ItemData(data[0] > 0, 0, QUALITIES.QUALITY_GOOD);
+ unsafe
+ {
+ fixed (byte* p = data)
+ {
+ short* p1 = (short*)p;
+ return new ItemData((*p1 & (1 << address.Bit.BitSwap()))
+ != 0, 0, QUALITIES.QUALITY_GOOD);
+ }
+ }
+ }
+ ///
+ /// 读object类型
+ ///
+ ///
+ ///
+ public ItemData