Browse Source

fix bug of modbustcp

pull/6/merge
Gavin 9 years ago
parent
commit
cef7455e64
  1. 8
      SCADA/Program/CoreTest/obj/x86/Debug/CoreTest_MarkupCompile.i.lref
  2. 607
      SCADA/Program/DataService/ClientReader.cs
  3. 4
      SCADA/Program/DataService/FCTCOMMAND.cs
  4. 180
      SCADA/Program/DataService/IModbusReader.cs
  5. 219
      SCADA/Program/DataService/Route.cs
  6. 385
      SCADA/Program/DataService/TagListGroup.cs
  7. 30
      SCADA/Program/DataService/WpfApplication1.sln
  8. BIN
      SCADA/Program/DataService/bin/Debug/DataService.dll
  9. 1219
      SCADA/Program/DataService/codeback.txt
  10. 1
      SCADA/Program/DataService/obj/Debug/DataService.csproj.FileListAbsolute.txt
  11. BIN
      SCADA/Program/DataService/obj/Debug/DataService.dll
  12. 63
      SCADA/Program/ModbusDriver/ModbusTCPDriver.cs
  13. BIN
      SCADA/Program/ModbusDriver/bin/Debug/DataService.dll
  14. BIN
      SCADA/Program/ModbusDriver/bin/Debug/ModbusDriver.dll
  15. BIN
      SCADA/Program/ModbusDriver/obj/Debug/ModbusDriver.dll
  16. BIN
      SCADA/dll/ModbusDriver.dll

8
SCADA/Program/CoreTest/obj/x86/Debug/CoreTest_MarkupCompile.i.lref

@ -0,0 +1,8 @@
C:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\CoreTest\obj\x86\Debug\GeneratedInternalTypeHelper.g.i.cs
FC:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\CoreTest\AlarmSet.xaml;;
FC:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\CoreTest\Guage.xaml;;
FC:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\CoreTest\MainWindow.xaml;;
FC:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\CoreTest\TagMonitor.xaml;;
FC:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\CoreTest\Trend.xaml;;

607
SCADA/Program/DataService/ClientReader.cs

@ -1,607 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
namespace DataService
{
public class ClientReader : IDevice
{
string _ip;
public string ServerName
{
get { return _ip; }
}
internal Socket tcpSynCl;
internal Socket tcpASynCl;
public bool IsClosed
{
get
{
//return tcpASynCl.Poll(-1, SelectMode.SelectRead);
return !tcpSynCl.Connected || !tcpASynCl.Connected;
}
}
private ushort _timeout = 0;
public int TimeOut
{
get { return _timeout; }
}
List<ClientGroup> _grps = new List<ClientGroup>(1);
public IEnumerable<IGroup> Groups
{
get { return _grps; }
}
IDataServer _server;
public IDataServer Parent
{
get { return _server; }
}
public ClientReader(IDataServer server, string ip)
{
_server = server;
_ip = ip;
}
public bool Connect()
{
try
{
int port = 1000;
IPAddress ip = IPAddress.Parse(_ip);
tcpASynCl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
tcpASynCl.Connect(new IPEndPoint(ip, port));
tcpASynCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, _timeout);
tcpASynCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, _timeout);
tcpSynCl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
tcpSynCl.Connect(new IPEndPoint(ip, port));
tcpSynCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, _timeout);
tcpSynCl.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, _timeout);
return true;
}
catch (SocketException error)
{
if (OnClose != null)
OnClose(this, new ShutdownRequestEventArgs(error.Message));
return false;
}
}
public IGroup AddGroup(string name, ushort id, int updateRate, int timeOut = 0, float deadBand = 0f, bool active = false)
{
ClientGroup grp = new ClientGroup(id, name, updateRate, active, this);
_grps.Add(grp);
return grp;
}
public int RemoveAllGroup()
{
foreach (IGroup grp in _grps)
{
grp.Dispose();
}
_grps.Clear();
return 1;
}
public event ShutdownRequestEventHandler OnClose;
public void Dispose()
{
if (tcpSynCl != null)
{
if (tcpSynCl.Connected)
{
try
{
tcpASynCl.Shutdown(SocketShutdown.Both);
tcpSynCl.Shutdown(SocketShutdown.Both);
}
catch { }
if (OnClose != null)
OnClose(this, new ShutdownRequestEventArgs("SHUTDOWN"));
tcpSynCl.Close();
tcpASynCl.Close();
}
tcpSynCl = null;
tcpASynCl = null;
}
RemoveAllGroup();
}
}
public class ClientGroup : IGroup
{
public const byte fctHead = 0xAB;
public const byte fctReadSingle = 1;
public const byte fctReadMultiple = 2;
public const byte fctWriteSingle = 5;
public const byte fctWriteMultiple = 15;
bool _active = false;
public bool IsActive
{
get
{
return _active;
}
set
{
_active = value;
if (value)
{
ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(ReciveData), _tcpASynCl);
}
}
}
protected ushort _id;
public ushort ID
{
get
{
return _id;
}
}
protected int _updateRate;
public int UpdateRate
{
get
{
return _updateRate;
}
set
{
_updateRate = value;
}
}
protected DeviceAddress _start;
public DeviceAddress Start
{
get
{
return _start;
}
}
public int Size
{
get
{
return _items == null ? 0 : _items.Length;
}
}
protected string _name;
public string Name
{
get
{
return _name;
}
}
protected float _deadband;
public float DeadBand
{
get
{
return _deadband;
}
set
{
_deadband = value;
}
}
protected ClientReader _plcReader;
public IDevice Parent
{
get
{
return _plcReader;
}
}
protected ITag[] _items;
public IEnumerable<ITag> Items
{
get { return _items; }
}
IDataServer _server;
Socket _tcpSynCl, _tcpASynCl;
byte[] tcpSynClBuffer;
public ClientGroup(ushort id, string name, int updateRate, bool active, ClientReader plcReader)
{
this._id = id;
this._name = name;
this._updateRate = updateRate;
this._active = active;
this._plcReader = plcReader;
this._server = plcReader.Parent;
this._tcpASynCl = plcReader.tcpASynCl;
this._tcpSynCl = plcReader.tcpASynCl;
tcpSynClBuffer = new byte[_tcpASynCl.ReceiveBufferSize];
}
private byte[] ReadSingleData(DeviceAddress address, DataSource source = DataSource.Cache)
{
short ID = (short)address.Start;
byte type = (byte)address.VarType;
byte[] idbits = BitConverter.GetBytes(ID);
byte[] write_data = new byte[6] { fctHead, fctReadSingle,
source == DataSource.Cache?(byte)0:(byte)1, idbits[0], idbits[1], type };
byte[] data = new byte[type < 4 ? 1 : type < 6 ? 2 : 4];
SocketError error;
_tcpSynCl.Send(write_data, 0, 6, SocketFlags.None, out error);
int result = _tcpSynCl.Receive(tcpSynClBuffer, 0, data.Length + 3, SocketFlags.None, out error);
Array.Copy(tcpSynClBuffer, 3, data, 0, data.Length);
if (error == SocketError.Success)
return data;
else
{
throw new SocketException((int)error);
}
}
private int WriteSingleData(DeviceAddress address, byte[] value)
{
short ID = (short)address.Start;
byte type = (byte)address.VarType;
byte[] idbits = BitConverter.GetBytes(ID);
byte[] write_data = new byte[6] { fctHead, fctWriteSingle, 1, idbits[0], idbits[1], type };
byte[] data = new byte[6 + value.Length];
write_data.CopyTo(data, 0);
value.CopyTo(data, 6);
SocketError error;
_tcpSynCl.Send(data, 0, data.Length, SocketFlags.None, out error);
int result = _tcpSynCl.Receive(tcpSynClBuffer, 0, 2, SocketFlags.None, out error);
if (error == SocketError.Success)
return tcpSynClBuffer[1];
else
{
throw new SocketException((int)error);
}
}
public void Init()
{
if (_items != null)
{
for (int i = 0; i < _items.Length; i++)
{
_items[i].Value = _items[i].Read(DataSource.Cache);//DataSource.Device
}
}
}
private void ReciveData(object state)
{
if (state == null || !_active) return;
byte[] bytes = new byte[_tcpASynCl.ReceiveBufferSize];
int result = 0;
SocketError error;
do
{
result = _tcpASynCl.Receive(bytes, 0, bytes.Length, SocketFlags.None, out error);
if (result > 5 && bytes[0] == 0xAB)
{
short len = BitConverter.ToInt16(bytes, 1);
short count = BitConverter.ToInt16(bytes, 3);
int j = 5;
DateTime time = DateTime.UtcNow;
Storage value = Storage.Empty;
for (int i = 0; i < count; i++)
{
short id = BitConverter.ToInt16(bytes, j);
j += 2;
ITag tag = GetItemByID(id);
if (tag != null)
{
DataType type = (DataType)bytes[j++];
switch (type)
{
case DataType.BOOL:
value.Boolean = BitConverter.ToBoolean(bytes, j++);
break;
case DataType.BYTE:
value.Byte = bytes[j++];
break;
case DataType.SHORT:
value.Int16 = BitConverter.ToInt16(bytes, j);
j += 2;
break;
case DataType.INT:
value.Int32 = BitConverter.ToInt32(bytes, j);
j += 4;
break;
case DataType.FLOAT:
value.Single = BitConverter.ToSingle(bytes, j);
j += 4;
break;
}
tag.Update(value, time, QUALITIES.QUALITY_GOOD);
}
else
{
byte type = bytes[j];
j += (type < 4 ? 2 : type < 6 ? 3 : 5);
}
}
//Array.Clear(bytes, 0, count);
}
}
while (result > 0);
}
public bool AddItems(ItemMetaData[] items)
{
int count = items.Length;
if (_items == null) _items = new ITag[count];
for (int i = 0; i < count; i++)
{
ITag dataItem = null;
ItemMetaData meta = items[i];
DeviceAddress addr = new DeviceAddress(0, 0, meta.ID, meta.Size, 0, meta.DataType);
switch (meta.DataType)
{
case DataType.BOOL:
dataItem = new BoolTag(meta.ID, addr, this);
break;
case DataType.BYTE:
dataItem = new ByteTag(meta.ID, addr, this);
break;
case DataType.WORD:
case DataType.SHORT:
dataItem = new ShortTag(meta.ID, addr, this);
break;
case DataType.TIME:
case DataType.INT:
dataItem = new IntTag(meta.ID, addr, this);
break;
case DataType.FLOAT:
dataItem = new FloatTag(meta.ID, addr, this);
break;
case DataType.STR:
dataItem = new StringTag(meta.ID, addr, this);
break;
default:
dataItem = new BoolTag(meta.ID, addr, this);
break;
}
_items[i] = dataItem;
_server.AddItemIndex(meta.Name, dataItem);
}
Array.Sort<ITag>(_items);
Init();
return true;
}
public bool RemoveAll()
{
Array.Clear(_items, 0, _items.Length);
return true;
}
public bool SetActiveState(bool active, params short[] items)
{
return true;
}
public int FindItemByAddress(DeviceAddress addr)
{
return Array.BinarySearch<ITag>(_items, new BoolTag(0, addr, null));
}
public ITag GetItemByID(short id)
{
return _server[id];
}
public int BatchRead(DataSource source, bool isSync, params ITag[] itemArray)
{
if (itemArray == null) return -1;
int len = itemArray.Length;
byte[] bt = new byte[4];
byte[] data = new byte[3 + len * 2];
int j=0;
data[j++] = fctHead;
data[j++] = fctReadMultiple;
data[j++] = source == DataSource.Cache ? (byte)0 : (byte)1;
bt = BitConverter.GetBytes(itemArray.Length);
data[j++] = bt[0];
data[j++] = bt[1];
data[j++] = bt[2];
data[j++] = bt[3];
for (int i = 0; i < len; i++)
{
ITag tag = itemArray[i];
bt = BitConverter.GetBytes(tag.ID);
data[j++] = bt[0];
data[j++] = bt[1];
data[j++] = (byte)(tag.Address.DataSize >> 3);
}
SocketError error;
_tcpSynCl.Send(data, 0, data.Length, SocketFlags.None, out error);
int result = _tcpSynCl.Receive(tcpSynClBuffer, 0, tcpSynClBuffer.Length, SocketFlags.None, out error);
j = 2;
if (error == SocketError.Success)
{
DateTime time=DateTime.UtcNow;
Storage value=Storage.Empty;
for (int i = 0; i < len; i++)
{
ITag tag = itemArray[i];
switch (tag.Address.VarType)
{
case DataType.BOOL:
value.Boolean = BitConverter.ToBoolean(tcpSynClBuffer, j++);
break;
case DataType.BYTE:
value.Byte = tcpSynClBuffer[j++];
break;
case DataType.SHORT:
value.Int16 = BitConverter.ToInt16(tcpSynClBuffer, j);
j += 2;
break;
case DataType.INT:
value.Int32 = BitConverter.ToInt32(tcpSynClBuffer, j);
j += 4;
break;
case DataType.FLOAT:
value.Single = BitConverter.ToSingle(tcpSynClBuffer, j);
j += 4;
break;
}
tag.Update(value, time, QUALITIES.QUALITY_GOOD);
}
return 0;
}
else
{
throw new SocketException((int)error);
}
}
public int BatchWrite(IDictionary<ITag, object> items, bool isSync = true)
{
List<byte> list = new List<byte>(new byte[] { fctHead, fctWriteMultiple });
list.AddRange(BitConverter.GetBytes(items.Count));
foreach (var item in items)
{
ITag tag = item.Key;
list.AddRange(BitConverter.GetBytes(tag.ID));
switch (tag.Address.VarType)
{
case DataType.BOOL:
list.Add((bool)item.Value ? (byte)1 : (byte)0);
break;
case DataType.BYTE:
list.Add((byte)item.Value);
break;
case DataType.SHORT:
list.AddRange(BitConverter.GetBytes((short)item.Value));
break;
case DataType.INT:
list.AddRange(BitConverter.GetBytes((int)item.Value));
break;
case DataType.FLOAT:
list.AddRange(BitConverter.GetBytes((float)item.Value));
break;
}
}
SocketError error;
_tcpSynCl.Send(list.ToArray(), 0, list.Count, SocketFlags.None, out error);
int result = _tcpSynCl.Receive(tcpSynClBuffer, 0, 2, SocketFlags.None, out error);
if (error == SocketError.Success)
return tcpSynClBuffer[1];
else
{
throw new SocketException((int)error);
}
}
public ItemData<int> ReadInt32(DeviceAddress address, DataSource source = DataSource.Cache)
{
var data = ReadSingleData(address, source);
return data == null ? new ItemData<int>(0, 0, QUALITIES.QUALITY_BAD) :
new ItemData<int>(BitConverter.ToInt32(data, 0), 0, QUALITIES.QUALITY_GOOD);
}
public ItemData<short> ReadInt16(DeviceAddress address, DataSource source = DataSource.Cache)
{
var data = ReadSingleData(address, source);
return data == null ? new ItemData<short>(0, 0, QUALITIES.QUALITY_BAD) :
new ItemData<short>(BitConverter.ToInt16(data, 0), 0, QUALITIES.QUALITY_GOOD);
}
public ItemData<byte> ReadByte(DeviceAddress address, DataSource source = DataSource.Cache)
{
var data = ReadSingleData(address, source);
return data == null ? new ItemData<byte>(0, 0, QUALITIES.QUALITY_BAD) :
new ItemData<byte>(data[0], 0, QUALITIES.QUALITY_GOOD);
}
public unsafe ItemData<float> ReadFloat(DeviceAddress address, DataSource source = DataSource.Cache)
{
var data = ReadSingleData(address, source);
if (data == null)
return new ItemData<float>(0.0f, 0, QUALITIES.QUALITY_BAD);
else
{
int value = BitConverter.ToInt32(data, 0);
return new ItemData<float>(*(((float*)&value)), 0, QUALITIES.QUALITY_GOOD);
}
}
public ItemData<bool> ReadBool(DeviceAddress address, DataSource source = DataSource.Cache)
{
var data = ReadSingleData(address, source);
return data == null ? new ItemData<bool>(false, 0, QUALITIES.QUALITY_BAD) :
new ItemData<bool>(BitConverter.ToBoolean(data, address.Bit), 0, QUALITIES.QUALITY_GOOD);
}
public ItemData<string> ReadString(DeviceAddress address, DataSource source = DataSource.Cache)
{
var data = ReadSingleData(address, source);
return data == null ? new ItemData<string>(string.Empty, 0, QUALITIES.QUALITY_BAD) :
new ItemData<string>(Encoding.Default.GetString(data, 0, address.DataSize), 0, QUALITIES.QUALITY_GOOD);
}
public int WriteInt32(DeviceAddress address, int value)
{
return WriteSingleData(address, BitConverter.GetBytes(value));
}
public int WriteInt16(DeviceAddress address, short value)
{
return WriteSingleData(address, BitConverter.GetBytes(value));
}
public int WriteFloat(DeviceAddress address, float value)
{
return WriteSingleData(address, BitConverter.GetBytes(value));
}
public int WriteString(DeviceAddress address, string value)
{
return WriteSingleData(address, Encoding.ASCII.GetBytes(value));
}
public int WriteBit(DeviceAddress address, bool value)
{
return WriteSingleData(address, new byte[] { (byte)(value ? 1 : 0) });
}
public int WriteBits(DeviceAddress address, byte value)
{
return WriteSingleData(address, new byte[] { value });
}
public event DataChangeEventHandler DataChange;
public void Dispose()
{
RemoveAll();
_items = null;
}
}
}

4
SCADA/Program/DataService/FCTCOMMAND.cs

@ -1,4 +0,0 @@
namespace DataService
{
}

180
SCADA/Program/DataService/IModbusReader.cs

@ -1,180 +0,0 @@
using System.Collections.Generic;
namespace DataService
{
public abstract class IModbusReader: IPLCDevice
{
public const byte fctReadCoil = 1;
public const byte fctReadDiscreteInputs = 2;
public const byte fctReadHoldingRegister = 3;
public const byte fctReadInputRegister = 4;
public const byte fctWriteSingleCoil = 5;
public const byte fctWriteSingleRegister = 6;
public const byte fctWriteMultipleCoils = 15;
public const byte fctWriteMultipleRegister = 16;
public const byte fctReadWriteMultipleRegister = 23;
public int PDU
{
get { return 0xFF; }
}
public int GetBlockSize(int area)
{
return area > 2 ? PDU / 2 : PDU;
}
public DeviceAddress GetDeviceAddress(string address)
{
DeviceAddress dv = DeviceAddress.Empty;
if (address == null || address.Length < 3)
return dv;
else
{
int index = address.IndexOf('.');
switch (address[0])
{
case '0':
dv.Area = fctReadCoil;
if (index > 0)
{
dv.Start = 64 * int.Parse(address.Substring(1, index - 1));
dv.Bit = byte.Parse(address.Substring(index + 1));
}
break;
case '1':
dv.Area = fctReadDiscreteInputs;
if (index > 0)
{
dv.Start = 64 * int.Parse(address.Substring(1, index - 1));
dv.Bit = byte.Parse(address.Substring(index + 1));
}
break;
case '4':
dv.Area = 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.Mid(1));
break;
case '3':
dv.Area = 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.Mid(1));
break;
}
}
return dv;
}
public string GetAddress(DeviceAddress address)
{
return string.Empty;
}
short _id;
public short ID
{
get
{
return _id;
}
}
string _server;
public string ServerName
{
get { return _server; }
set { _server = value; }
}
public abstract DeviceDriver Driver
{
get ;
}
public abstract bool IsClosed
{
get;
}
private int _timeout;
public int TimeOut
{
get { return _timeout; }
set { _timeout = value; }
}
List<IGroup> _grps = new List<IGroup>(20);
public IEnumerable<IGroup> Groups
{
get { return _grps; }
}
IDataServer _parent;
public IDataServer Parent
{
get { return _parent; }
}
public abstract bool Connect();
public IGroup AddGroup(string name, short id, int updateRate, float deadBand = 0f, bool active = false)
{
ModbusGroup grp = new ModbusGroup(id, name, updateRate, active, this);
_grps.Add(grp);
return grp;
}
public bool RemoveGroup(IGroup grp)
{
grp.IsActive = false;
return _grps.Remove(grp);
}
public event ShutdownRequestEventHandler OnClose;
public abstract void Dispose();
public abstract byte[] ReadBytes(DeviceAddress address, ushort size);
public abstract ItemData<int> ReadInt32(DeviceAddress address);
public abstract ItemData<short> ReadInt16(DeviceAddress address);
public abstract ItemData<byte> ReadByte(DeviceAddress address);
public abstract ItemData<string> ReadString(DeviceAddress address, ushort size);
public abstract ItemData<float> ReadFloat(DeviceAddress address);
public abstract ItemData<bool> ReadBit(DeviceAddress address);
public abstract ItemData<object> ReadValue(DeviceAddress address);
public abstract int WriteBytes(DeviceAddress address, byte[] bit);
public abstract int WriteBit(DeviceAddress address, bool bit);
public abstract int WriteBits(DeviceAddress address, byte bits);
public abstract int WriteInt16(DeviceAddress address, short value);
public abstract int WriteInt32(DeviceAddress address, int value);
public abstract int WriteFloat(DeviceAddress address, float value);
public abstract int WriteString(DeviceAddress address, string str);
public abstract int WriteValue(DeviceAddress address, object value);
}
}

219
SCADA/Program/DataService/Route.cs

@ -1,219 +0,0 @@
using System;
using System.Collections.Generic;
namespace DataService
{
[Flags]
public enum DevStatus
{
None = 0,
RUN = 0x0001,
STOP = 0x0002,
OLS = 0x0004,
CLS = 0x0008,
PAUSE = 0x0010,
READY = 0x0020,
DUMP = 0x0040,
COMPLETE = 0x0080,
ALARM = 0x0100,
}
[Flags]
public enum DevCommand
{
START = 0x0001,
STOP = 0x0002,
ABORT = 0x0004,
PAUSE = 0x0008,
HOLD = 0x0010,
WET = 0x0020,
DISCH = 0x0040,
DUMP = 0x0080,
}
public interface IDevice : IComparable<IDevice>
{
string Name { get; }
string Description { get; }
DeviceTypes DeviceType { get; }
int ExtStatus { get; }
DevStatus Status { get; }
int Execute(DevCommand command);
}
//可以根据订单的源仓目标仓,二分法搜索到仓的列表。得到仓的参数和状态;部分设备是互斥的(如闸门,分配器,三通),马达等是共用的。
public sealed class RouteVex : IComparable<RouteVex>, IEqualityComparer<RouteVex>
{
string _source;
public string Source
{
get { return _source; }
}
string _dest;
public string Dest
{
get { return _dest; }
}
RouteVex _front;
public RouteVex Front
{
get { return _front; }
set { _front = value; }
}
Func<bool> _func;
Func<int> _funcWrite;
public bool IsRun
{
get { return _func == null ? true : _func(); }
}
public RouteVex(string source, string dest = "")
{
_source = source;
_dest = dest;
}
public RouteVex(string source, string dest, string startSignal, string runSignal, IDataServer srv)
{
_source = source;
_dest = dest;
var eval = srv.Eval;
if (!string.IsNullOrEmpty(runSignal))
{
_func = eval.Eval(runSignal) as Func<bool>;
}
if (!string.IsNullOrEmpty(startSignal))
{
_funcWrite = eval.WriteEval(startSignal) as Func<int>;
}
}
public int Start()
{
return _funcWrite == null ? 0 : _funcWrite();
}
public int CompareTo(RouteVex other)
{
if (this._source == null) return 0;
if (other._dest == null) return 1;
int comp = this._source.CompareTo(other._source);
return comp == 0 ? this._dest.CompareTo(other._dest) : comp;
}
public override string ToString()
{
return string.Concat(_source, ",", _dest);
}
public bool Equals(RouteVex x, RouteVex y)
{
if (x == null || y == null) return false;
return ((x.Source == null && y.Source == null) || (x.Source == y.Source)) &&
((x.Dest == null && y.Dest == null) || (x.Dest == y.Dest));
}
public int GetHashCode(RouteVex obj)
{
return obj.Source.GetHashCode() ^ obj.Dest.GetHashCode();
}
}
//正在执行的路径,保存到一个XML文件,包含当前执行的节点
public sealed class Route : LinkedList<RouteVex>, ICloneable
{
LinkedListNode<RouteVex> _current;
public LinkedListNode<RouteVex> Current
{
get { return _current; }
set { _current = value; }
}
string _start;
public string Start
{
get { return _start; }
set { _start = value; }
}
string _end;
public string End
{
get { return _end; }
set { _end = value; }
}
RouteState _state;
public RouteState State
{
get { return _state; }
set { _state = value; }
}
string[] _options;
public string[] Options
{
get { return _options; }
set { _options = value; }
}
public Route(string source, string dest, string[] options = null)
{
_start = source;
_end = dest;
_options = options;
}
public object Clone()
{
Route rt = new Route(_start, _end, _options);
foreach (var routeVex in this)
{
rt.AddLast(routeVex);
}
return rt;
}
}
public enum DeviceTypes
{
Misc,
Motor = 1,
Valve = 2,
Gate = 3,
Divert = 4,
FourWays = 5,
Distribute = 6,
Bin = 7,
Analog = 8,
Scale = 9,
Conveyor = 10,
Elevator = 11,
Mixer = 12,
Grind = 13,
Pellet = 14,
Extruder = 15,
CheckScale = 16,
Liquid = 17,
HandAdd = 18,
Sifter = 19,
Cyclone = 20,
AirHammer = 21
}
public enum RouteState
{
Idle,
Run,
Stop,
Suspend,
Complete,
Abort,
}
}

385
SCADA/Program/DataService/TagListGroup.cs

@ -1,385 +0,0 @@
using System.Collections.Generic;
using System.Threading;
namespace DataService
{
public class TagListGroup : IGroup
{
bool _isActive, _isDisposed;
public bool IsActive
{
get
{
return _isActive;
}
set
{
_isActive = value;
if (value)
{
ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(this.OnUpdate), 1);
}
}
}
short _id;
public short ID
{
get
{
return _id;
}
}
int _updateRate;
public int UpdateRate
{
get
{
return _updateRate;
}
set
{
_updateRate = value;
}
}
string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
float deadband;
public float DeadBand
{
get
{
return deadband;
}
set
{
deadband = value;
}
}
IPLCDriver _reader;
public IDriver Parent
{
get { return _reader; }
}
List<ITag> _items;
public IEnumerable<ITag> Items
{
get { return _items; }
}
IDataServer _server;
public IDataServer Server
{
get
{
return _server;
}
}
HashSet<short> _activeList;
CompareItemByID rc = new CompareItemByID();
public TagListGroup(short id, string name, int updateRate, int size, bool active, IPLCDriver plcReader)
{
this._id = id;
this._updateRate = updateRate;
this._isActive = active;
this._reader = plcReader;
this._name = name;
this._server = _reader.Parent;
}
public bool AddItems(IList<TagMetaData> items)
{
int count = items.Count;
if (_items == null)
{
_items = new List<ITag>(count);
_activeList = new HashSet<short>();
}
lock (_server.SyncRoot)
{
for (int i = 0; i < count; i++)
{
ITag dataItem = null;
TagMetaData meta = items[i];
if (meta.GroupID == this._id)
{
switch (meta.DataType)
{
case DataType.BOOL:
dataItem = new BoolTag(meta.ID, _reader.GetDeviceAddress(meta.Address), this);
break;
case DataType.BYTE:
dataItem = new ByteTag(meta.ID, _reader.GetDeviceAddress(meta.Address), this);
break;
case DataType.WORD:
case DataType.SHORT:
dataItem = new ShortTag(meta.ID, _reader.GetDeviceAddress(meta.Address), this);
break;
case DataType.TIME:
case DataType.INT:
dataItem = new IntTag(meta.ID, _reader.GetDeviceAddress(meta.Address), this);
break;
case DataType.FLOAT:
dataItem = new FloatTag(meta.ID, _reader.GetDeviceAddress(meta.Address), this);
break;
case DataType.STR:
dataItem = new StringTag(meta.ID, _reader.GetDeviceAddress(meta.Address), this);
break;
}
if (dataItem != null)
{
_items.Add(dataItem);
_server.AddItemIndex(meta.Name, dataItem);
_activeList.Add(meta.ID);
}
}
}
}
_items.Sort(rc);
_items.TrimExcess();
return true;
}
public bool AddTags(IEnumerable<ITag> tags)
{
if (_items == null)
{
_items = new List<ITag>();
}
foreach (ITag tag in tags)
{
if (tag != null)
{
_items.Add(tag);
if (tag.Active)
{
_activeList.Add(tag.ID);
}
}
}
_items.Sort(rc);
_items.TrimExcess();
return true;
}
public bool RemoveItems(params ITag[] items)
{
foreach (var item in items)
{
_server.RemoveItemIndex(item.GetTagName());
_activeList.Remove(item.ID);
_items.Remove(item);
}
return true;
}
public bool SetActiveState(bool active, params short[] items)
{
if (active)
{
lock (_activeList)
{
_activeList.UnionWith(items);
};
}
else
{
lock (_activeList)
{
_activeList.ExceptWith(items);
};
}
return true;
}
public ITag FindItemByAddress(DeviceAddress addr)
{
for (int i = 0; i < _items.Count; i++)
{
DeviceAddress address = _items[i].Address;
if (addr.Area == address.Area
&& addr.DBNumber == address.DBNumber
&& addr.Start == address.Start
&& addr.Bit == address.Bit)
return _items[i];
}
return null;
}
public HistoryData[] BatchRead(DataSource source, bool isSync, params ITag[] itemArray)
{
return ExtMethods.BatchRead(source, itemArray);
}
public int BatchWrite(SortedDictionary<ITag, object> items, bool isSync = true)
{
int rev = ExtMethods.BatchWrite(items);
if (DataChange != null && rev >= 0)
{
int len = items.Count;
HistoryData[] data = new HistoryData[len];
int i = 0;
foreach (var item in items)
{
ITag tag = item.Key;
data[i].ID = tag.ID;
data[i].TimeStamp = tag.TimeStamp;
data[i].Quality = tag.Quality;
data[i].Value = item.Key.ToStorage(item.Value);
i++;
}
foreach (DataChangeEventHandler deleg in DataChange.GetInvocationList())
{
deleg.BeginInvoke(this, new DataChangeEventArgs(1, data), null, null);
}
}
return rev;
}
public ItemData<int> ReadInt32(DeviceAddress address, DataSource source = DataSource.Cache)
{
return _reader.ReadInt32(address);
}
public ItemData<short> ReadInt16(DeviceAddress address, DataSource source = DataSource.Cache)
{
return _reader.ReadInt16(address);
}
public ItemData<byte> ReadByte(DeviceAddress address, DataSource source = DataSource.Cache)
{
return _reader.ReadByte(address);
}
public ItemData<float> ReadFloat(DeviceAddress address, DataSource source = DataSource.Cache)
{
return _reader.ReadFloat(address);
}
public ItemData<bool> ReadBool(DeviceAddress address, DataSource source = DataSource.Cache)
{
return _reader.ReadBit(address);
}
public ItemData<string> ReadString(DeviceAddress address, DataSource source = DataSource.Cache)
{
return new ItemData<string>(string.Empty, 0, QUALITIES.QUALITY_UNCERTAIN);
}
public int WriteInt32(DeviceAddress address, int value)
{
return _reader.WriteInt32(address, value);
}
public int WriteInt16(DeviceAddress address, short value)
{
return _reader.WriteInt16(address, value);
}
public int WriteFloat(DeviceAddress address, float value)
{
return _reader.WriteFloat(address, value);
}
public int WriteString(DeviceAddress address, string value)
{
return _reader.WriteString(address, value);
}
public int WriteBit(DeviceAddress address, bool value)
{
return _reader.WriteBit(address, value);
}
public int WriteBits(DeviceAddress address, byte value)
{
return _reader.WriteBits(address, value);
}
public void Dispose()
{
_items.Clear();
_activeList.Clear();
_isDisposed = true;
//Dictionary<int, string> dict = new Dictionary<int, string>();
}
public void OnUpdate(object stateInfo)
{
while (true)
{
Thread.Sleep(_updateRate);
lock (this)
{
if (!_isActive || _isDisposed)
{
return;
}
List<HistoryData> hdalist = new List<HistoryData>();
foreach (short id in _activeList)
{
ITag item = _server[id];
if (item != null)
{
if (item.Refresh() && DataChange != null)
hdalist.Add(new HistoryData(item.ID, item.Quality, item.Value, item.TimeStamp));
}
if (DataChange != null)
DataChange.BeginInvoke(this, new DataChangeEventArgs(1, hdalist), null, null);
}
}
}
}
public event DataChangeEventHandler DataChange;
}
public class CompareItemByID : IComparer<ITag>
{
public int Compare(ITag x, ITag y)
{
if (x == null)
{
if (y == null)
{
return 0;
}
else
{
return -1;
}
}
else
{
if (y == null)
{
return 1;
}
else
{
return x.ID.CompareTo(y.ID);
}
}
}
}
}

30
SCADA/Program/DataService/WpfApplication1.sln

@ -1,30 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataService", "DataService.csproj", "{8965E389-6466-4B30-BD43-83C909044637}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8965E389-6466-4B30-BD43-83C909044637}.Debug|Any CPU.ActiveCfg = Debug|x86
{8965E389-6466-4B30-BD43-83C909044637}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{8965E389-6466-4B30-BD43-83C909044637}.Debug|Mixed Platforms.Build.0 = Debug|x86
{8965E389-6466-4B30-BD43-83C909044637}.Debug|x86.ActiveCfg = Debug|x86
{8965E389-6466-4B30-BD43-83C909044637}.Debug|x86.Build.0 = Debug|x86
{8965E389-6466-4B30-BD43-83C909044637}.Release|Any CPU.ActiveCfg = Release|x86
{8965E389-6466-4B30-BD43-83C909044637}.Release|Mixed Platforms.ActiveCfg = Release|x86
{8965E389-6466-4B30-BD43-83C909044637}.Release|Mixed Platforms.Build.0 = Release|x86
{8965E389-6466-4B30-BD43-83C909044637}.Release|x86.ActiveCfg = Release|x86
{8965E389-6466-4B30-BD43-83C909044637}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

BIN
SCADA/Program/DataService/bin/Debug/DataService.dll

Binary file not shown.

1219
SCADA/Program/DataService/codeback.txt

File diff suppressed because it is too large

1
SCADA/Program/DataService/obj/Debug/DataService.csproj.FileListAbsolute.txt

@ -22,3 +22,4 @@ C:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\DataService\bin\Debug\D
C:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\DataService\bin\Debug\DataService.pdb
C:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\DataService\obj\Debug\DataService.dll
C:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\DataService\obj\Debug\DataService.pdb
C:\Users\Yinan\Documents\Github\SharpSCADA\SCADA\Program\DataService\obj\Debug\DataService.csprojResolveAssemblyReference.cache

BIN
SCADA/Program/DataService/obj/Debug/DataService.dll

Binary file not shown.

63
SCADA/Program/ModbusDriver/ModbusTCPDriver.cs

@ -56,6 +56,16 @@ namespace ModbusDriver
set { _timeout = value; }
}
byte _slaveId;//设备ID 单元号 字节号
/// <summary>
/// 设备ID 单元号 字节号
/// </summary>
public byte SlaveId
{
get { return _slaveId; }
set { _slaveId = value; }
}
List<IGroup> _grps = new List<IGroup>(20);
public IEnumerable<IGroup> Groups
{
@ -75,6 +85,7 @@ namespace ModbusDriver
_server = server;
_ip = ip;
_timeout = timeOut;
byte.TryParse(spare1, out _slaveId);
}
public bool Connect()
@ -105,12 +116,10 @@ namespace ModbusDriver
private byte[] CreateReadHeader(int id, int startAddress, ushort length, byte function)
{
byte[] data = new byte[12];
byte[] _id = BitConverter.GetBytes((short)id);
data[0] = _id[0]; // Slave id high byte
data[1] = _id[1]; // Slave id low byte
data[0] = 0; // Slave id high byte
data[1] = 0; // Slave id low byte
data[5] = 6; // Message size
data[6] = 0; // Slave address
data[6] = (byte)id; // Slave address
data[7] = function; // Function code
byte[] _adr = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)startAddress));
data[8] = _adr[0]; // Start address
@ -124,14 +133,12 @@ namespace ModbusDriver
private byte[] CreateWriteHeader(int id, int startAddress, ushort numData, ushort numBytes, byte function)
{
byte[] data = new byte[numBytes + 11];
byte[] _id = BitConverter.GetBytes(id);
data[0] = _id[0]; // Slave id high byte
data[1] = _id[1]; // Slave id low byte+
data[0] = 0; // Slave id high byte
data[1] = 0; // Slave id low byte+
byte[] _size = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)(5 + numBytes)));
data[4] = _size[0]; // Complete message size in bytes
data[5] = _size[1]; // Complete message size in bytes
data[6] = 0; // Slave address
data[6] = (byte)id; // Slave address
data[7] = function; // Function code
byte[] _adr = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)startAddress));
data[8] = _adr[0]; // Start address
@ -243,11 +250,12 @@ namespace ModbusDriver
DeviceAddress dv = DeviceAddress.Empty;
if (string.IsNullOrEmpty(address))
return dv;
dv.Area = _slaveId;
switch (address[0])
{
case '0':
{
dv.Area = Modbus.fctReadCoil;
dv.DBNumber = Modbus.fctReadCoil;
int st;
int.TryParse(address, out st);
//dv.Start = (st / 16) * 16;//???????????????????
@ -258,7 +266,7 @@ namespace ModbusDriver
break;
case '1':
{
dv.Area = Modbus.fctReadDiscreteInputs;
dv.DBNumber = Modbus.fctReadDiscreteInputs;
int st;
int.TryParse(address.Substring(1), out st);
//dv.Start = (st / 16) * 16;//???????????????????
@ -270,7 +278,7 @@ namespace ModbusDriver
case '4':
{
int index = address.IndexOf('.');
dv.Area = Modbus.fctReadHoldingRegister;
dv.DBNumber = Modbus.fctReadHoldingRegister;
if (index > 0)
{
dv.Start = int.Parse(address.Substring(1, index - 1));
@ -284,7 +292,7 @@ namespace ModbusDriver
case '3':
{
int index = address.IndexOf('.');
dv.Area = Modbus.fctReadInputRegister;
dv.DBNumber = Modbus.fctReadInputRegister;
if (index > 0)
{
dv.Start = int.Parse(address.Substring(1, index - 1));
@ -381,14 +389,14 @@ namespace ModbusDriver
public byte[] ReadBytes(DeviceAddress address, ushort size)
{
int area = address.Area;
return area < 2 ? WriteSyncData(CreateReadHeader(area, address.Start * 16, (ushort)(16 * size), (byte)area))
: WriteSyncData(CreateReadHeader(area, address.Start, size, (byte)area));
int area = address.DBNumber;
return area < 2 ? WriteSyncData(CreateReadHeader(address.Area, address.Start * 16, (ushort)(16 * size), (byte)area))
: WriteSyncData(CreateReadHeader(address.Area, address.Start, size, (byte)area));
}
public ItemData<int> ReadInt32(DeviceAddress address)
{
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, 2, (byte)address.Area));
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, 2, (byte)address.DBNumber));
if (data == null)
return new ItemData<int>(0, 0, QUALITIES.QUALITY_BAD);
else
@ -397,7 +405,7 @@ namespace ModbusDriver
public ItemData<short> ReadInt16(DeviceAddress address)
{
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, 1, (byte)address.Area));
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, 1, (byte)address.DBNumber));
if (data == null)
return new ItemData<short>(0, 0, QUALITIES.QUALITY_BAD);
else
@ -406,7 +414,7 @@ namespace ModbusDriver
public ItemData<byte> ReadByte(DeviceAddress address)
{
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, 1, (byte)address.Area));
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, 1, (byte)address.DBNumber));
if (data == null)
return new ItemData<byte>(0, 0, QUALITIES.QUALITY_BAD);
else
@ -415,7 +423,7 @@ namespace ModbusDriver
public ItemData<string> ReadString(DeviceAddress address, ushort size)
{
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, size, (byte)address.Area));
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, size, (byte)address.DBNumber));
if (data == null)
return new ItemData<string>(string.Empty, 0, QUALITIES.QUALITY_BAD);
else
@ -424,7 +432,7 @@ namespace ModbusDriver
public unsafe ItemData<float> ReadFloat(DeviceAddress address)
{
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, 2, (byte)address.Area));
byte[] data = WriteSyncData(CreateReadHeader(address.Area, address.Start, 2, (byte)address.DBNumber));
if (data == null)
return new ItemData<float>(0.0f, 0, QUALITIES.QUALITY_BAD);
else
@ -436,10 +444,11 @@ namespace ModbusDriver
public ItemData<bool> ReadBit(DeviceAddress address)
{
byte[] data = address.Area > 2 ? WriteSyncData(CreateReadHeader(address.Area, address.Start, 1, (byte)address.Area)) :
WriteSyncData(CreateReadHeader(address.Area, address.Start + address.Bit, 1, (byte)address.Area));
byte[] data = address.DBNumber > 2 ? WriteSyncData(CreateReadHeader(address.Area, address.Start, 1, (byte)address.DBNumber)) :
WriteSyncData(CreateReadHeader(address.Area, address.Start * 16 + address.Bit, 1, (byte)address.DBNumber));
if (data == null)
return new ItemData<bool>(false, 0, QUALITIES.QUALITY_BAD);
if (data.Length == 1) return new ItemData<bool>(data[0] > 0, 0, QUALITIES.QUALITY_GOOD);
unsafe
{
fixed (byte* p = data)
@ -458,14 +467,14 @@ namespace ModbusDriver
public int WriteBytes(DeviceAddress address, byte[] bit)
{
var data = address.Area > 2 ? WriteMultipleRegister(address.Area, address.Start, bit)
var data = address.DBNumber > 2 ? WriteMultipleRegister(address.Area, address.Start, bit)
: WriteMultipleCoils(address.Area, address.Start, (ushort)(8 * bit.Length), bit);//应考虑到
return data == null ? -1 : 0;
}
public int WriteBit(DeviceAddress address, bool bit)
{
if (address.Area < 3)
if (address.DBNumber < 3)
{
var data = WriteSingleCoils(address.Area, address.Start + address.Bit, bit);
return data == null ? -1 : 0;
@ -574,7 +583,7 @@ namespace ModbusDriver
{
while (addr.Start == next.Start)
{
if ((tmp & (1 << next.Bit.BitSwap())) > 0) _changedList.Add(index);
if ((tmp & (1 << next.Bit)) > 0) _changedList.Add(index);
if (++index < count)
next = _items[index].Address;
else

BIN
SCADA/Program/ModbusDriver/bin/Debug/DataService.dll

Binary file not shown.

BIN
SCADA/Program/ModbusDriver/bin/Debug/ModbusDriver.dll

Binary file not shown.

BIN
SCADA/Program/ModbusDriver/obj/Debug/ModbusDriver.dll

Binary file not shown.

BIN
SCADA/dll/ModbusDriver.dll

Binary file not shown.
Loading…
Cancel
Save