diff --git a/SCADA/Program/DataService/Alarm.cs b/SCADA/Program/DataService/Alarm.cs index 523fadc..a3feac5 100644 --- a/SCADA/Program/DataService/Alarm.cs +++ b/SCADA/Program/DataService/Alarm.cs @@ -157,67 +157,4 @@ namespace DataService } - [Flags] - public enum AlarmType - { - None = 0, - Level = 1, - Dev = 2, - Dsc = 4, - ROC = 8, - Quality = 16, - Complex = 32, - WordDsc = 64 - } - - [Flags] - public enum SubAlarmType - { - None = 0, - LoLo = 1, - Low = 2, - High = 4, - HiHi = 8, - MajDev = 16, - MinDev = 32, - Dsc = 64, - - BadPV = 128, - MajROC = 256, - MinROC = 512 - } - - public enum Severity - { - Error = 7, - High = 6, - MediumHigh = 5, - Medium = 4, - MediumLow = 3, - Low = 2, - Information = 1, - Normal = 0 - } - - [Flags] - public enum ConditionState : byte - { - Acked = 4, - Actived = 2, - Enabled = 1 - } - - public enum EventType : byte - { - Simple = 1, - TraceEvent = 2, - ConditionEvent = 4, - } - - public enum ConditionType : byte - { - Absolute = 0, - Percent = 1 - } - } diff --git a/SCADA/Program/DataService/CacheReader.cs b/SCADA/Program/DataService/CacheReader.cs index ac64220..e8eb183 100644 --- a/SCADA/Program/DataService/CacheReader.cs +++ b/SCADA/Program/DataService/CacheReader.cs @@ -503,7 +503,7 @@ namespace DataService public unsafe ItemData ReadBit(DeviceAddress address) { - return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit.BitSwap())) != 0, 0, QUALITIES.QUALITY_GOOD); + return new ItemData((_cache[address.CacheIndex] & (1 << address.Bit)) != 0, 0, QUALITIES.QUALITY_GOOD); } public ItemData ReadInt16(DeviceAddress address) @@ -551,7 +551,7 @@ namespace DataService public int WriteBit(DeviceAddress address, bool bit) { - _cache[address.CacheIndex] |= (short)(1 << address.Bit.BitSwap()); + _cache[address.CacheIndex] |= (short)(1 << address.Bit); return 0; } diff --git a/SCADA/Program/DataService/DataService.csproj b/SCADA/Program/DataService/DataService.csproj index b811665..d77019b 100644 --- a/SCADA/Program/DataService/DataService.csproj +++ b/SCADA/Program/DataService/DataService.csproj @@ -158,6 +158,7 @@ + diff --git a/SCADA/Program/DataService/DeviceAddress.cs b/SCADA/Program/DataService/DeviceAddress.cs index 927ec42..16a2648 100644 --- a/SCADA/Program/DataService/DeviceAddress.cs +++ b/SCADA/Program/DataService/DeviceAddress.cs @@ -13,8 +13,9 @@ namespace DataService public ushort CacheIndex; public byte Bit; public DataType VarType; + public ByteOrder ByteOrder; - public DeviceAddress(int area, ushort dbnumber, ushort cIndex, int start, ushort size, byte bit, DataType type) + public DeviceAddress(int area, ushort dbnumber, ushort cIndex, int start, ushort size, byte bit, DataType type, ByteOrder order = ByteOrder.None) { Area = area; DBNumber = dbnumber; @@ -23,6 +24,7 @@ namespace DataService DataSize = size; Bit = bit; VarType = type; + ByteOrder = order; } public static readonly DeviceAddress Empty = new DeviceAddress(0, 0, 0, 0, 0, 0, DataType.NONE); diff --git a/SCADA/Program/DataService/Enums.cs b/SCADA/Program/DataService/Enums.cs new file mode 100644 index 0000000..ce7b7c1 --- /dev/null +++ b/SCADA/Program/DataService/Enums.cs @@ -0,0 +1,99 @@ +using System; + +namespace DataService +{ + + public enum DataSource + { + Cache = 1, + Device = 2 + } + + public enum DataType : byte + { + NONE = 0, + BOOL = 1, + BYTE = 3, + SHORT = 4, + WORD = 5, + TIME = 6, + INT = 7, + FLOAT = 8, + SYS = 9, + STR = 11 + } + + [Flags] + public enum ByteOrder : byte + { + None = 0, + BigEndian = 1, + LittleEndian = 2, + Network = 4, + Host = 8 + } + + + [Flags] + public enum AlarmType + { + None = 0, + Level = 1, + Dev = 2, + Dsc = 4, + ROC = 8, + Quality = 16, + Complex = 32, + WordDsc = 64 + } + + [Flags] + public enum SubAlarmType + { + None = 0, + LoLo = 1, + Low = 2, + High = 4, + HiHi = 8, + MajDev = 16, + MinDev = 32, + Dsc = 64, + + BadPV = 128, + MajROC = 256, + MinROC = 512 + } + + public enum Severity + { + Error = 7, + High = 6, + MediumHigh = 5, + Medium = 4, + MediumLow = 3, + Low = 2, + Information = 1, + Normal = 0 + } + + [Flags] + public enum ConditionState : byte + { + Acked = 4, + Actived = 2, + Enabled = 1 + } + + public enum EventType : byte + { + Simple = 1, + TraceEvent = 2, + ConditionEvent = 4, + } + + public enum ConditionType : byte + { + Absolute = 0, + Percent = 1 + } +} diff --git a/SCADA/Program/DataService/ITag.cs b/SCADA/Program/DataService/ITag.cs index a08c8df..f9f314d 100644 --- a/SCADA/Program/DataService/ITag.cs +++ b/SCADA/Program/DataService/ITag.cs @@ -579,26 +579,6 @@ namespace DataService } } - public enum DataSource - { - Cache = 1, - Device = 2 - } - - public enum DataType : byte - { - NONE = 0, - BOOL = 1, - BYTE = 3, - SHORT = 4, - WORD = 5, - TIME = 6, - INT = 7, - FLOAT = 8, - SYS = 9, - STR = 11 - } - public delegate void ValueChangingEventHandler(object sender, ValueChangingEventArgs e); public delegate void ValueChangedEventHandler(object sender, ValueChangedEventArgs e); diff --git a/SCADA/Program/DataService/PLCGroup.cs b/SCADA/Program/DataService/PLCGroup.cs index 0040a54..a125ae2 100644 --- a/SCADA/Program/DataService/PLCGroup.cs +++ b/SCADA/Program/DataService/PLCGroup.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Net; using System.Timers; namespace DataService @@ -683,4 +684,278 @@ namespace DataService Count = count; } } + + public sealed class NetBytePLCGroup : PLCGroup + { + public NetBytePLCGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) + { + this._id = id; + this._name = name; + this._updateRate = updateRate; + this._isActive = active; + this._plcReader = plcReader; + this._server = _plcReader.Parent; + this._timer = new Timer(); + this._changedList = new List(); + this._cacheReader = new NetByteCacheReader(); + } + + protected override void Poll() + { + if (_items == null || _items.Count == 0) return; + byte[] cache = (byte[])_cacheReader.Cache; + int offset = 0; + foreach (PDUArea area in _rangeList) + { + byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据 + if (rcvBytes == null) + { + //_plcReader.Connect(); + continue; + } + else + { + int index = area.StartIndex;//index指向_items中的Tag元数据 + int count = index + area.Count; + while (index < count) + { + DeviceAddress addr = _items[index].Address; + int iByte = addr.CacheIndex; + int iByte1 = iByte - offset; + if (addr.VarType == DataType.BOOL) + { + int tmp = rcvBytes[iByte1] ^ cache[iByte]; + DeviceAddress next = addr; + if (tmp != 0) + { + while (addr.Start == next.Start) + { + if ((tmp & (1 << next.Bit)) > 0) _changedList.Add(index); + if (++index < count) + next = _items[index].Address; + else + break; + } + } + else + { + while (addr.Start == next.Start && ++index < count) + { + next = _items[index].Address; + } + } + } + else + { + ushort size = addr.DataSize; + for (int i = 0; i < size; i++) + { + if (iByte1 + i < rcvBytes.Length && rcvBytes[iByte1 + i] != cache[iByte + i]) + { + _changedList.Add(index); + break; + } + } + index++; + } + } + for (int j = 0; j < rcvBytes.Length; j++) + cache[j + offset] = rcvBytes[j];//将PLC读取的数据写入到CacheReader中 + } + offset += rcvBytes.Length; + } + } + } + + public sealed class NetShortGroup : PLCGroup + { + public NetShortGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) + { + this._id = id; + this._name = name; + this._updateRate = updateRate; + this._isActive = active; + this._plcReader = plcReader; + this._server = _plcReader.Parent; + this._timer = new Timer(); + this._changedList = new List(); + this._cacheReader = new NetShortCacheReader(); + } + + protected override unsafe void Poll() + { + short[] cache = (short[])_cacheReader.Cache; + int offset = 0; + foreach (PDUArea area in _rangeList) + { + byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据 + if (rcvBytes == null || rcvBytes.Length == 0) + { + offset += (area.Len + 1) / 2; + //_plcReader.Connect(); + continue; + } + else + { + int len = rcvBytes.Length / 2; + fixed (byte* p1 = rcvBytes) + { + short* prcv = (short*)p1; + int index = area.StartIndex;//index指向_items中的Tag元数据 + int count = index + area.Count; + while (index < count) + { + DeviceAddress addr = _items[index].Address; + int iShort = addr.CacheIndex; + int iShort1 = iShort - offset; + if (addr.VarType == DataType.BOOL) + { + if (addr.ByteOrder.HasFlag(ByteOrder.Network)) prcv[iShort1] = IPAddress.HostToNetworkOrder(prcv[iShort1]); + int tmp = prcv[iShort1] ^ cache[iShort]; + DeviceAddress next = addr; + if (tmp != 0) + { + while (addr.Start == next.Start) + { + if ((tmp & (1 << next.Bit)) > 0) _changedList.Add(index); + if (++index < count) + next = _items[index].Address; + else + break; + } + } + else + { + while (addr.Start == next.Start && ++index < count) + { + next = _items[index].Address; + } + } + } + else + { + if (addr.DataSize <= 2) + { + if (prcv[iShort1] != cache[iShort]) _changedList.Add(index); + } + else + { + int size = addr.DataSize / 2; + for (int i = 0; i < size; i++) + { + if (prcv[iShort1 + i] != cache[iShort + i]) + { + _changedList.Add(index); + break; + } + } + } + index++; + } + } + for (int j = 0; j < len; j++) + { + cache[j + offset] = prcv[j]; + }//将PLC读取的数据写入到CacheReader中 + } + offset += len; + } + } + } + } + + public sealed class ShortGroup : PLCGroup + { + public ShortGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) + { + this._id = id; + this._name = name; + this._updateRate = updateRate; + this._isActive = active; + this._plcReader = plcReader; + this._server = _plcReader.Parent; + this._timer = new Timer(); + this._changedList = new List(); + this._cacheReader = new ShortCacheReader(); + } + + protected override unsafe void Poll() + { + short[] cache = (short[])_cacheReader.Cache; + int k = 0; + foreach (PDUArea area in _rangeList) + { + byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据 + if (rcvBytes == null) + { + continue; + } + else + { + int len = rcvBytes.Length / 2; + fixed (byte* p1 = rcvBytes) + { + short* prcv = (short*)p1; + int index = area.StartIndex;//index指向_items中的Tag元数据 + int count = index + area.Count; + while (index < count) + { + DeviceAddress addr = _items[index].Address; + int iShort = addr.CacheIndex; + int iShort1 = iShort - k; + if (addr.VarType == DataType.BOOL) + { + int tmp = prcv[iShort1] ^ cache[iShort]; + DeviceAddress next = addr; + if (tmp != 0) + { + while (addr.Start == next.Start) + { + if ((tmp & (1 << next.Bit)) > 0) _changedList.Add(index); + if (++index < count) + next = _items[index].Address; + else + break; + } + } + else + { + while (addr.Start == next.Start && ++index < count) + { + next = _items[index].Address; + } + } + } + else + { + if (addr.DataSize <= 2) + { + if (prcv[iShort1] != cache[iShort]) _changedList.Add(index); + } + else + { + int size = addr.DataSize / 2; + for (int i = 0; i < size; i++) + { + if (prcv[iShort1 + i] != cache[iShort + i]) + { + _changedList.Add(index); + break; + } + } + } + index++; + } + } + for (int j = 0; j < len; j++) + { + cache[j + k] = prcv[j]; + }//将PLC读取的数据写入到CacheReader中 + } + k += len; + } + } + } + + } } diff --git a/SCADA/Program/ModbusDriver/ModbusDriver.csproj b/SCADA/Program/ModbusDriver/ModbusDriver.csproj index d57f61d..afea990 100644 --- a/SCADA/Program/ModbusDriver/ModbusDriver.csproj +++ b/SCADA/Program/ModbusDriver/ModbusDriver.csproj @@ -104,7 +104,6 @@ - diff --git a/SCADA/Program/ModbusDriver/ModbusRTUDriver.cs b/SCADA/Program/ModbusDriver/ModbusRTUDriver.cs index dc6a133..03295a6 100644 --- a/SCADA/Program/ModbusDriver/ModbusRTUDriver.cs +++ b/SCADA/Program/ModbusDriver/ModbusRTUDriver.cs @@ -151,8 +151,8 @@ namespace ModbusDriver data[0] = _slaveId; // Slave id high byte data[1] = Modbus.fctWriteSingleCoil; // Function code byte[] _adr = BitConverter.GetBytes((short)startAddress); - data[2] = _adr[0]; // Start address - data[3] = _adr[1]; // Start address + data[2] = _adr[1]; // Start address + data[3] = _adr[0]; // Start address if (OnOff) data[4] = 0xFF; byte[] arr = Utility.CalculateCrc(data, 6); data[6] = arr[0]; @@ -169,11 +169,11 @@ namespace ModbusDriver data[0] = _slaveId; // Slave id high byte 从站地址高八位 data[1] = Modbus.fctWriteMultipleCoils; // Function code 功能码 byte[] _adr = BitConverter.GetBytes((short)startAddress); - data[2] = _adr[0]; // Start address 开始地址高八位 - data[3] = _adr[1]; // Start address 开始地址低八位 + data[2] = _adr[1]; // Start address 开始地址高八位 + data[3] = _adr[0]; // Start address 开始地址低八位 byte[] _length = BitConverter.GetBytes((short)numBits); - data[4] = _length[0]; // Number of data to read 寄存器数量高八位 - data[5] = _length[1]; // Number of data to read 寄存器数量低八位 + data[4] = _length[1]; // Number of data to read 寄存器数量高八位 + data[5] = _length[0]; // Number of data to read 寄存器数量低八位 data[6] = (byte)len; //字节数量 Array.Copy(values, 0, data, 7, len); //在data中加入变更数据 byte[] arr = Utility.CalculateCrc(data, len + 7); @@ -190,10 +190,10 @@ namespace ModbusDriver data[0] = _slaveId; // Slave id high byte 从站地址高八位 data[1] = Modbus.fctWriteSingleRegister; // Function code 功能码 byte[] _adr = BitConverter.GetBytes((short)startAddress); - data[2] = _adr[0]; // Start address 开始地址高八位 - data[3] = _adr[1]; // Start address 开始地址高八位 - data[4] = values[0]; //变更数据的高位 - data[5] = values[1]; //变更数据的低位 + data[2] = _adr[1]; // Start address 开始地址高八位 + data[3] = _adr[0]; // Start address 开始地址高八位 + data[4] = values[1]; //变更数据的高位 + data[5] = values[0]; //变更数据的低位 byte[] arr = Utility.CalculateCrc(data, 6); data[6] = arr[0]; //CRC校验码低八位 data[7] = arr[1]; //CRC校验码高八位 @@ -210,11 +210,11 @@ namespace ModbusDriver data[0] = _slaveId; // Slave id high byte 从站地址 data[1] = Modbus.fctWriteMultipleRegister; // Function code 功能码 byte[] _adr = BitConverter.GetBytes((short)startAddress); - data[2] = _adr[0]; // Start address 开始地址高八位 - data[3] = _adr[1]; // Start address 开始地址低八位 + data[2] = _adr[1]; // Start address 开始地址高八位 + data[3] = _adr[0]; // Start address 开始地址低八位 byte[] _length = BitConverter.GetBytes((short)(len >> 1)); - data[4] = _length[0]; // Number of data to read 寄存器数量高八位 - data[5] = _length[1]; // Number of data to read 寄存器数量低八位 + data[4] = _length[1]; // Number of data to read 寄存器数量高八位 + data[5] = _length[0]; // Number of data to read 寄存器数量低八位 data[6] = (byte)len; //字节数 Array.Copy(values, 0, data, 7, len); //把变更数据加入data中 byte[] arr = Utility.CalculateCrc(data, len + 7); diff --git a/SCADA/Program/ModbusDriver/ModbusRTU_TCP.cs b/SCADA/Program/ModbusDriver/ModbusRTU_TCP.cs deleted file mode 100644 index e8243f0..0000000 --- a/SCADA/Program/ModbusDriver/ModbusRTU_TCP.cs +++ /dev/null @@ -1,462 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Net.Sockets; -using System.Text; -using DataService; - -namespace ModbusDriver -{ - [Description("Modbus RTU_TCP协议")] - public sealed class ModbusRTU_TCPReader : IPLCDriver, IMultiReadWrite - { - private int _timeout; - - private Socket tcpSynCl; - private byte[] tcpSynClBuffer = new byte[0xFF]; - - short _id; - public short ID - { - get - { - return _id; - } - } - - string _name; - public string Name - { - get - { - return _name; - } - } - - int _slave = 1; - string _ip; - public string ServerName - { - get { return _ip; } - set { _ip = value; } - } - - public bool IsClosed - { - get - { - return tcpSynCl == null || tcpSynCl.Connected == false; - } - } - - public int TimeOut - { - get { return _timeout; } - set { _timeout = value; } - } - - List _grps = new List(20); - public IEnumerable Groups - { - get { return _grps; } - } - - IDataServer _server; - public IDataServer Parent - { - get { return _server; } - } - - public ModbusRTU_TCPReader(IDataServer server, short id, string name, string ip, int timeOut = 500, string spare1 = "1", string spare2 = null) - { - _id = id;//id - _name = name; - _server = server; - _ip = ip; - _timeout = timeOut; - if (!string.IsNullOrEmpty(spare1)) - _slave = int.Parse(spare1); - } - - public bool Connect() - { - int port = 7000; - try - { - if (tcpSynCl != null) - tcpSynCl.Close(); - //IPAddress ip = IPAddress.Parse(_ip); - // ---------------------------------------------------------------- - // Connect synchronous client - tcpSynCl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - tcpSynCl.SendTimeout = _timeout; - tcpSynCl.ReceiveTimeout = _timeout; - tcpSynCl.NoDelay = true; - tcpSynCl.Connect(_ip, port); - return true; - } - catch (SocketException error) - { - if (OnClose != null) - OnClose(this, new ShutdownRequestEventArgs(error.Message)); - return false; - } - } - - private byte[] CreateReadHeader(int startAddress, ushort length, byte function) - { - byte[] data = new byte[8]; - data[0] = (byte)_slave; // Slave id high byte - data[1] = function; // Message size - byte[] _adr = BitConverter.GetBytes((short)startAddress); - data[2] = _adr[0]; // Start address - data[3] = _adr[1]; // Start address - byte[] _length = BitConverter.GetBytes((short)length); - data[4] = _length[0]; // Number of data to read - data[5] = _length[1]; // Number of data to read - byte[] arr = Utility.CalculateCrc(data, 6); - data[6] = arr[0]; - data[7] = arr[1]; - return data; - } - - public byte[] WriteSingleCoils(int startAddress, bool OnOff) - { - byte[] data = new byte[8]; - data[0] = (byte)_slave; // Slave id high byte - data[1] = Modbus.fctWriteSingleCoil; // Function code - byte[] _adr = BitConverter.GetBytes((short)startAddress); - data[2] = _adr[0]; // Start address - data[3] = _adr[1]; // Start address - if (OnOff) data[4] = 0xFF; - byte[] arr = Utility.CalculateCrc(data, 6); - data[6] = arr[0]; - data[7] = arr[1]; - return data; - } - - public byte[] WriteMultipleCoils(int startAddress, ushort numBits, byte[] values) - { - int len = values.Length; - byte[] data = new byte[len + 9]; - data[0] = (byte)_slave; // Slave id high byte - data[1] = Modbus.fctWriteMultipleCoils; // Function code - byte[] _adr = BitConverter.GetBytes((short)startAddress); - data[2] = _adr[0]; // Start address - data[3] = _adr[1]; // Start address - byte[] _length = BitConverter.GetBytes((short)numBits); - data[4] = _length[0]; // Number of data to read - data[5] = _length[1]; // Number of data to read - data[6] = (byte)len; - Array.Copy(values, 0, data, 7, len); - byte[] arr = Utility.CalculateCrc(data, len + 7); - data[len + 7] = arr[0]; - data[len + 8] = arr[1]; - return data; - } - - public byte[] WriteSingleRegister(int startAddress, byte[] values) - { - byte[] data = new byte[8]; - data[0] = (byte)_slave; // Slave id high byte - data[1] = Modbus.fctWriteSingleRegister; // Function code - byte[] _adr = BitConverter.GetBytes((short)startAddress); - data[2] = _adr[0]; // Start address - data[3] = _adr[1]; // Start address - data[4] = values[0]; - data[5] = values[1]; - byte[] arr = Utility.CalculateCrc(data, 6); - data[6] = arr[0]; - data[7] = arr[1]; - return data; - } - - public byte[] WriteMultipleRegister(int startAddress, byte[] values) - { - int len = values.Length; - if (len % 2 > 0) len++; - byte[] data = new byte[len + 9]; - data[0] = (byte)_slave; // Slave id high byte - data[1] = Modbus.fctWriteMultipleRegister; // Function code - byte[] _adr = BitConverter.GetBytes((short)startAddress); - data[2] = _adr[0]; // Start address - data[3] = _adr[1]; // Start address - byte[] _length = BitConverter.GetBytes((short)(len >> 1)); - data[4] = _length[0]; // Number of data to read - data[5] = _length[1]; // Number of data to read - data[6] = (byte)len; - Array.Copy(values, 0, data, 7, len); - byte[] arr = Utility.CalculateCrc(data, len + 7); - data[len + 7] = arr[0]; - data[len + 8] = arr[1]; - return data; - } - - public int PDU - { - get { return 252; } - //get { return 256; } - } - - public DeviceAddress GetDeviceAddress(string address) - { - DeviceAddress dv = DeviceAddress.Empty; - if (string.IsNullOrEmpty(address)) - return dv; - switch (address[0]) - { - case '0': - { - dv.Area = Modbus.fctReadCoil; - int st; - int.TryParse(address, out st); - //dv.Start = (st / 16) * 16;//??????????????????? - dv.Bit = (byte)(st % 16); - st /= 16; - dv.Start = st; - } - break; - case '1': - { - dv.Area = Modbus.fctReadDiscreteInputs; - int st; - int.TryParse(address.Substring(1), out st); - //dv.Start = (st / 16) * 16;//??????????????????? - dv.Bit = (byte)(st % 16); - st /= 16; - dv.Start = st; - } - break; - case '4': - { - int index = address.IndexOf('.'); - dv.Area = Modbus.fctReadHoldingRegister; - 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)); - dv.Start--; - } - break; - case '3': - { - int index = address.IndexOf('.'); - dv.Area = Modbus.fctReadInputRegister; - 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)); - dv.Start--; - } - break; - } - return dv; - } - - public string GetAddress(DeviceAddress address) - { - return string.Empty; - } - - - public IGroup AddGroup(string name, short id, int updateRate, float deadBand = 0f, bool active = false) - { - ModbusTcpGroup grp = new ModbusTcpGroup(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 (tcpSynCl != null) - { - if (tcpSynCl.Connected) - { - try { tcpSynCl.Shutdown(SocketShutdown.Both); } - catch { } - tcpSynCl.Close(); - } - tcpSynCl = null; - } - foreach (IGroup grp in _grps) - { - grp.Dispose(); - } - _grps.Clear(); - } - - public byte[] ReadBytes(DeviceAddress address, ushort size) - { - int area = address.Area; - try - { - if (!tcpSynCl.Connected) return null; - byte[] header = area == Modbus.fctReadCoil ? CreateReadHeader(address.Start * 16, (ushort)(16 * size), (byte)area) : - CreateReadHeader(address.Start, size, (byte)area); - tcpSynCl.Send(header, 0, header.Length, SocketFlags.None);//是否存在lock的问题? - byte[] frameBytes = new byte[size * 2 + 3]; - int result = tcpSynCl.Receive(frameBytes, 0, frameBytes.Length, SocketFlags.None); - byte[] data = new byte[size * 2]; - if (frameBytes[0] == (byte)_slave) - { - Array.Copy(frameBytes, 3, data, 0, data.Length); - return data; - } - else return new byte[0]; - } - catch (Exception e) - { - if (OnClose != null) - OnClose(this, new ShutdownRequestEventArgs(e.Message)); - return null; - } - } - - public ItemData ReadInt32(DeviceAddress address) - { - byte[] bit = ReadBytes(address, 2); - return bit == null ? new ItemData(0, 0, QUALITIES.QUALITY_BAD) : - new ItemData(BitConverter.ToInt32(bit, 0), 0, QUALITIES.QUALITY_GOOD); - } - - public ItemData ReadInt16(DeviceAddress address) - { - byte[] bit = ReadBytes(address, 1); - return bit == null ? new ItemData(0, 0, QUALITIES.QUALITY_BAD) : - new ItemData(BitConverter.ToInt16(bit, 0), 0, QUALITIES.QUALITY_GOOD); - } - - public ItemData ReadByte(DeviceAddress address) - { - byte[] bit = ReadBytes(address, 1); - return bit == null ? new ItemData(0, 0, QUALITIES.QUALITY_BAD) : - new ItemData(bit[0], 0, QUALITIES.QUALITY_GOOD); - } - - public ItemData ReadString(DeviceAddress address, ushort size) - { - byte[] bit = ReadBytes(address, size); - return bit == null ? new ItemData(string.Empty, 0, QUALITIES.QUALITY_BAD) : - new ItemData(Encoding.ASCII.GetString(bit), 0, QUALITIES.QUALITY_GOOD); - } - - public unsafe ItemData ReadFloat(DeviceAddress address) - { - byte[] bit = ReadBytes(address, 2); - return bit == null ? new ItemData(0f, 0, QUALITIES.QUALITY_BAD) : - new ItemData(BitConverter.ToSingle(bit, 0), 0, QUALITIES.QUALITY_GOOD); - //int value = BitConverter.ToInt32(bit, 0); - //return new ItemData(*(((float*)&value)), 0, QUALITIES.QUALITY_GOOD); - } - - public ItemData ReadBit(DeviceAddress address) - { - byte[] bit = ReadBytes(address, 1); - return bit == null ? new ItemData(false, 0, QUALITIES.QUALITY_BAD) : - new ItemData((bit[0] & (1 << (address.Bit))) > 0, 0, QUALITIES.QUALITY_GOOD); - } - - public ItemData ReadValue(DeviceAddress address) - { - return this.ReadValueEx(address); - } - - public int WriteBytes(DeviceAddress address, byte[] bit) - { - if (!tcpSynCl.Connected) return -1; - var data = WriteMultipleRegister(address.Start, bit); - tcpSynCl.Send(data, 0, data.Length, SocketFlags.None);//是否存在lock的问题? - int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 0xFF, SocketFlags.None); - return (tcpSynClBuffer[1] & 0x80) > 0 ? -1 : 0; - } - - public int WriteBit(DeviceAddress address, bool bit) - { - if (!tcpSynCl.Connected) return -1; - var data = WriteSingleCoils(address.Start + address.Bit, bit); - tcpSynCl.Send(data, 0, data.Length, SocketFlags.None);//是否存在lock的问题? - int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 0xFF, SocketFlags.None); - return (tcpSynClBuffer[1] & 0x80) > 0 ? -1 : 0; - } - - public int WriteBits(DeviceAddress address, byte bits) - { - if (!tcpSynCl.Connected) return -1; - var data = WriteSingleRegister(address.Start, new byte[] { bits }); - tcpSynCl.Send(data, 0, data.Length, SocketFlags.None);//是否存在lock的问题? - int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 0xFF, SocketFlags.None); - return (tcpSynClBuffer[1] & 0x80) > 0 ? -1 : 0; - } - - public int WriteInt16(DeviceAddress address, short value) - { - if (!tcpSynCl.Connected) return -1; - var data = WriteSingleRegister(address.Start, BitConverter.GetBytes(value)); - tcpSynCl.Send(data, 0, data.Length, SocketFlags.None);//是否存在lock的问题? - int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 0xFF, SocketFlags.None); - return (tcpSynClBuffer[1] & 0x80) > 0 ? -1 : 0; - } - - public int WriteInt32(DeviceAddress address, int value) - { - if (!tcpSynCl.Connected) return -1; - var data = WriteMultipleRegister(address.Start, BitConverter.GetBytes(value)); - tcpSynCl.Send(data, 0, data.Length, SocketFlags.None);//是否存在lock的问题? - int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 0xFF, SocketFlags.None); - return (tcpSynClBuffer[1] & 0x80) > 0 ? -1 : 0; - } - - public int WriteFloat(DeviceAddress address, float value) - { - if (!tcpSynCl.Connected) return -1; - var data = WriteMultipleRegister(address.Start, BitConverter.GetBytes(value)); - tcpSynCl.Send(data, 0, data.Length, SocketFlags.None);//是否存在lock的问题? - int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 0xFF, SocketFlags.None); - return (tcpSynClBuffer[1] & 0x80) > 0 ? -1 : 0; - } - - public int WriteString(DeviceAddress address, string str) - { - if (!tcpSynCl.Connected) return -1; - var data = WriteMultipleRegister(address.Start, Encoding.ASCII.GetBytes(str)); - tcpSynCl.Send(data, 0, data.Length, SocketFlags.None);//是否存在lock的问题? - int result = tcpSynCl.Receive(tcpSynClBuffer, 0, 0xFF, SocketFlags.None); - return (tcpSynClBuffer[1] & 0x80) > 0 ? -1 : 0; - } - - public int WriteValue(DeviceAddress address, object value) - { - return this.WriteValueEx(address, value); - } - - public event ShutdownRequestEventHandler OnClose; - - public int Limit - { - get { return 60; } - } - - public ItemData[] ReadMultiple(DeviceAddress[] addrsArr) - { - return this.PLCReadMultiple(new NetShortCacheReader(), addrsArr); - } - - public int WriteMultiple(DeviceAddress[] addrArr, object[] buffer) - { - return this.PLCWriteMultiple(new NetShortCacheReader(), addrArr, buffer, Limit); - } - } -} - diff --git a/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs b/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs index c540f75..db25d08 100644 --- a/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs +++ b/SCADA/Program/ModbusDriver/ModbusTCPDriver.cs @@ -44,6 +44,7 @@ namespace ModbusDriver dv.Bit = (byte)(st % 16); st /= 16; dv.Start = st; + dv.Bit--; } break; case '1': @@ -55,6 +56,7 @@ namespace ModbusDriver dv.Bit = (byte)(st % 16); st /= 16; dv.Start = st; + dv.Bit--; } break; case '4': @@ -69,6 +71,8 @@ namespace ModbusDriver else dv.Start = int.Parse(address.Substring(1)); dv.Start--; + dv.Bit--; + dv.ByteOrder = ByteOrder.Network; } break; case '3': @@ -83,6 +87,8 @@ namespace ModbusDriver else dv.Start = int.Parse(address.Substring(1)); dv.Start--; + dv.Bit--; + dv.ByteOrder = ByteOrder.Network; } break; } @@ -328,7 +334,7 @@ namespace ModbusDriver public IGroup AddGroup(string name, short id, int updateRate, float deadBand = 0f, bool active = false) { - ModbusTcpGroup grp = new ModbusTcpGroup(id, name, updateRate, active, this); + NetShortGroup grp = new NetShortGroup(id, name, updateRate, active, this); _grps.Add(grp); return grp; } @@ -393,11 +399,8 @@ namespace ModbusDriver internal void CallException(int id, byte function, byte exception) { if (tcpSynCl == null) return; - if (exception == Modbus.excExceptionConnectionLost && IsClosed == false) - { - if (OnClose != null) - OnClose(this, new ShutdownRequestEventArgs(GetErrorString(exception))); - } + if (OnClose != null) + OnClose(this, new ShutdownRequestEventArgs(GetErrorString(exception))); } public byte[] ReadBytes(DeviceAddress address, ushort size) @@ -547,101 +550,4 @@ namespace ModbusDriver return this.PLCWriteMultiple(new NetShortCacheReader(), addrArr, buffer, Limit); } } - - public sealed class ModbusTcpGroup : PLCGroup - { - public ModbusTcpGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) - { - this._id = id; - this._name = name; - this._updateRate = updateRate; - this._isActive = active; - this._plcReader = plcReader; - this._server = _plcReader.Parent; - this._timer = new Timer(); - this._changedList = new List(); - this._cacheReader = new NetShortCacheReader(); - } - - protected override unsafe void Poll() - { - short[] cache = (short[])_cacheReader.Cache; - int offset = 0; - foreach (PDUArea area in _rangeList) - { - byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据 - if (rcvBytes == null || rcvBytes.Length == 0) - { - //offset += area.Len / 2; - //_plcReader.Connect(); - continue; - } - else - { - int len = rcvBytes.Length / 2; - fixed (byte* p1 = rcvBytes) - { - short* prcv = (short*)p1; - int index = area.StartIndex;//index指向_items中的Tag元数据 - int count = index + area.Count; - while (index < count) - { - DeviceAddress addr = _items[index].Address; - int iShort = addr.CacheIndex; - int iShort1 = iShort - offset; - if (addr.VarType == DataType.BOOL) - { - int tmp = prcv[iShort1] ^ cache[iShort]; - DeviceAddress next = addr; - if (tmp != 0) - { - while (addr.Start == next.Start) - { - if ((tmp & (1 << next.Bit.BitSwap())) > 0) _changedList.Add(index); - if (++index < count) - next = _items[index].Address; - else - break; - } - } - else - { - while (addr.Start == next.Start && ++index < count) - { - next = _items[index].Address; - } - } - } - else - { - if (addr.DataSize <= 2) - { - if (prcv[iShort1] != cache[iShort]) _changedList.Add(index); - } - else - { - int size = addr.DataSize / 2; - for (int i = 0; i < size; i++) - { - if (prcv[iShort1 + i] != cache[iShort + i]) - { - _changedList.Add(index); - break; - } - } - } - index++; - } - } - for (int j = 0; j < len; j++) - { - cache[j + offset] = prcv[j]; - }//将PLC读取的数据写入到CacheReader中 - } - offset += len; - } - } - } - - } } diff --git a/SCADA/Program/OmronPlcDriver/OmronUdpReader.cs b/SCADA/Program/OmronPlcDriver/OmronUdpReader.cs index e8a5e15..8562a82 100644 --- a/SCADA/Program/OmronPlcDriver/OmronUdpReader.cs +++ b/SCADA/Program/OmronPlcDriver/OmronUdpReader.cs @@ -108,6 +108,7 @@ namespace OmronPlcDriver } break; } + dv.ByteOrder = ByteOrder.Network; return dv; } @@ -434,7 +435,7 @@ namespace OmronPlcDriver public IGroup AddGroup(string name, short id, int updateRate, float deadBand = 0f, bool active = false) { - OmronCsCjUDPGroup grp = new OmronCsCjUDPGroup(id, name, updateRate, active, this); + NetShortGroup grp = new NetShortGroup(id, name, updateRate, active, this); _grps.Add(grp); return grp; } @@ -694,106 +695,6 @@ namespace OmronPlcDriver } } - public sealed class OmronCsCjUDPGroup : PLCGroup - { - public OmronCsCjUDPGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) - { - this._id = id; - this._name = name; - this._updateRate = updateRate; - this._isActive = active; - this._plcReader = plcReader; - this._server = _plcReader.Parent; - this._timer = new Timer(); - this._changedList = new List(); - this._cacheReader = new NetShortCacheReader(); - } - - protected override unsafe void Poll() - { - //Console.WriteLine("开始遍历》》"); - short[] cache = (short[])_cacheReader.Cache; - int offset = 0; - foreach (PDUArea area in _rangeList) - { - //Console.WriteLine(">>读取:" + area.Start.DBNumber.ToString() + "@" + DateTime.Now.ToString()); - byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据 - if (rcvBytes == null || rcvBytes.Length == 0) - { - //Console.WriteLine(">>结果:" + area.Start.DBNumber.ToString() + "->失败"); - continue; - } - else - { - //Console.WriteLine(">>结果:" + area.Start.DBNumber.ToString() + "->" + BitConverter.ToString(rcvBytes) + " at" + DateTime.Now.ToString()); - int len = area.Len;// rcvBytes.Length / 2; - fixed (byte* p1 = rcvBytes) - { - short* prcv = (short*)p1; - int index = area.StartIndex;//index指向_items中的Tag元数据 - int count = index + area.Count; - while (index < count) - { - DeviceAddress addr = _items[index].Address; - int iShort = addr.CacheIndex; - int iShort1 = iShort - offset; - if (addr.VarType == DataType.BOOL) - { - int tmp = prcv[iShort1] ^ cache[iShort]; - DeviceAddress next = addr; - if (tmp != 0) - { - while (addr.Start == next.Start) - { - if ((tmp & 1 << next.Bit.BitSwap()) > 0) - _changedList.Add(index); - if (++index < count) - next = _items[index].Address; - else - break; - } - } - else - { - while (addr.Start == next.Start && ++index < count) - { - next = _items[index].Address; - } - } - } - else - { - if (addr.DataSize <= 2) - { - - if (prcv[iShort1] != cache[iShort]) _changedList.Add(index); - } - else - { - int size = addr.DataSize / 2; - for (int i = 0; i < size; i++) - { - if (prcv[iShort1 + i] != cache[iShort + i]) - { - _changedList.Add(index); - break; - } - } - } - index++; - } - } - for (int j = 0; j < len; j++) - { - cache[j + offset] = prcv[j]; - }//将PLC读取的数据写入到CacheReader中 - } - offset += len; - } - } - } - } - /// /// 欧姆龙Omron CS/CJ系列PLC数据区功能号和错误代码常数定义类 /// diff --git a/SCADA/Program/PanasonicDriver/PanasonicSerialReader.cs b/SCADA/Program/PanasonicDriver/PanasonicSerialReader.cs index 802ac82..8ec1488 100644 --- a/SCADA/Program/PanasonicDriver/PanasonicSerialReader.cs +++ b/SCADA/Program/PanasonicDriver/PanasonicSerialReader.cs @@ -94,7 +94,7 @@ namespace PanasonicPLCriver public IGroup AddGroup(string name, short id, int updateRate, float deadBand = 0, bool active = false) { - PanasonicGroup grp = new PanasonicGroup(id, name, updateRate, active, this); + NetShortGroup grp = new NetShortGroup(id, name, updateRate, active, this); _grps.Add(grp); return grp; } @@ -211,6 +211,7 @@ namespace PanasonicPLCriver break; } } + dv.ByteOrder = ByteOrder.Network; return dv; } #region 实现了四个命令 其余没有做 @@ -554,100 +555,6 @@ namespace PanasonicPLCriver } #endregion } - public sealed class PanasonicGroup : PLCGroup - { - public PanasonicGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) - { - this._id = id; - this._name = name; - this._updateRate = updateRate; - this._isActive = active; - this._plcReader = plcReader; - this._server = _plcReader.Parent; - this._timer = new System.Timers.Timer(); - this._changedList = new List(); - this._cacheReader = new NetShortCacheReader(); - } - - protected override void Poll() - { - short[] cache = (short[])_cacheReader.Cache; - int offset = 0; - foreach (PDUArea area in _rangeList) - { - byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据 - if (rcvBytes == null || rcvBytes.Length == 0) - { - continue; - } - else - { - int len = rcvBytes.Length / 2; - short[] prcv = new short[rcvBytes.Length / 2]; - for (int i = 0; i < prcv.Length; i++) - prcv[i] = IPAddress.HostToNetworkOrder(BitConverter.ToInt16(rcvBytes, i * 2)); - int index = area.StartIndex;//index指向_items中的Tag元数据 - int count = index + area.Count; - while (index < count) - { - DeviceAddress addr = _items[index].Address; - int iShort = addr.CacheIndex; - int iShort1 = iShort - offset; - if (addr.VarType == DataType.BOOL) - { - short tt = prcv[iShort1]; - short tmp = IPAddress.HostToNetworkOrder((short)(tt ^ cache[iShort])); - DeviceAddress next = addr; - if (tmp != 0) - { - while (addr.Start == next.Start) - { - short ne = (short)(1 << next.Bit); - if ((tmp & (ne)) > 0) _changedList.Add(index); - if (++index < count) - next = _items[index].Address; - else - break; - } - } - else - { - while (addr.Start == next.Start && ++index < count) - { - next = _items[index].Address; - } - } - } - else - { - if (addr.DataSize <= 2) - { - if (prcv[iShort1] != cache[iShort]) _changedList.Add(index); - } - else - { - int size = addr.DataSize / 2; - for (int i = 0; i < size; i++) - { - if (prcv[iShort1 + i] != cache[iShort + i]) - { - _changedList.Add(index); - break; - } - } - } - index++; - } - } - for (int j = 0; j < len; j++) - { - cache[j + offset] = prcv[j]; - }//将PLC读取的数据写入到CacheReader中 - offset += len; - } - } - } - } public struct Panasonic { diff --git a/SCADA/Program/SiemensPLCDriver/SiemensPLCDriver.cs b/SCADA/Program/SiemensPLCDriver/SiemensPLCDriver.cs index 8933f61..f09e4fe 100644 --- a/SCADA/Program/SiemensPLCDriver/SiemensPLCDriver.cs +++ b/SCADA/Program/SiemensPLCDriver/SiemensPLCDriver.cs @@ -719,85 +719,4 @@ namespace SiemensPLCDriver public event ShutdownRequestEventHandler OnClose; } - public sealed class NetBytePLCGroup : PLCGroup - { - public NetBytePLCGroup(short id, string name, int updateRate, bool active, IPLCDriver plcReader) - { - this._id = id; - this._name = name; - this._updateRate = updateRate; - this._isActive = active; - this._plcReader = plcReader; - this._server = _plcReader.Parent; - this._timer = new Timer(); - this._changedList = new List(); - this._cacheReader = new NetByteCacheReader(); - } - - protected override void Poll() - { - if (_items == null || _items.Count == 0) return; - byte[] cache = (byte[])_cacheReader.Cache; - int offset = 0; - foreach (PDUArea area in _rangeList) - { - byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据 - if (rcvBytes == null) - { - //_plcReader.Connect(); - continue; - } - else - { - int index = area.StartIndex;//index指向_items中的Tag元数据 - int count = index + area.Count; - while (index < count) - { - DeviceAddress addr = _items[index].Address; - int iByte = addr.CacheIndex; - int iByte1 = iByte - offset; - if (addr.VarType == DataType.BOOL) - { - int tmp = rcvBytes[iByte1] ^ cache[iByte]; - DeviceAddress next = addr; - if (tmp != 0) - { - while (addr.Start == next.Start) - { - if ((tmp & (1 << next.Bit)) > 0) _changedList.Add(index); - if (++index < count) - next = _items[index].Address; - else - break; - } - } - else - { - while (addr.Start == next.Start && ++index < count) - { - next = _items[index].Address; - } - } - } - else - { - ushort size = addr.DataSize; - for (int i = 0; i < size; i++) - { - if (iByte1 + i < rcvBytes.Length && rcvBytes[iByte1 + i] != cache[iByte + i]) - { - _changedList.Add(index); - break; - } - } - index++; - } - } - for (int j = 0; j < rcvBytes.Length; j++) - cache[j + offset] = rcvBytes[j];//将PLC读取的数据写入到CacheReader中 - } - offset += rcvBytes.Length; - } - } - } } diff --git a/SCADA/dll/DataService.dll b/SCADA/dll/DataService.dll index d916294..63c7cfb 100644 Binary files a/SCADA/dll/DataService.dll and b/SCADA/dll/DataService.dll differ diff --git a/SCADA/dll/ModbusDriver.dll b/SCADA/dll/ModbusDriver.dll index a2c1311..dcda474 100644 Binary files a/SCADA/dll/ModbusDriver.dll and b/SCADA/dll/ModbusDriver.dll differ diff --git a/SCADA/dll/OmronPlcDriver.dll b/SCADA/dll/OmronPlcDriver.dll index 40ee386..7d62b05 100644 Binary files a/SCADA/dll/OmronPlcDriver.dll and b/SCADA/dll/OmronPlcDriver.dll differ diff --git a/SCADA/dll/PanasonicDriver.dll b/SCADA/dll/PanasonicDriver.dll index 730dfad..2510552 100644 Binary files a/SCADA/dll/PanasonicDriver.dll and b/SCADA/dll/PanasonicDriver.dll differ diff --git a/SCADA/dll/SiemensPLCDriver.dll b/SCADA/dll/SiemensPLCDriver.dll index 632f720..f4b0759 100644 Binary files a/SCADA/dll/SiemensPLCDriver.dll and b/SCADA/dll/SiemensPLCDriver.dll differ