forked from tsai/SharpSCADA
16 changed files with 985 additions and 3 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,518 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using System.Text; |
||||
|
using System.Timers; |
||||
|
using DataService; |
||||
|
using Tuxeip; |
||||
|
|
||||
|
namespace ABPLCDriver |
||||
|
{ |
||||
|
[Description("EtherNet IP协议")] |
||||
|
public unsafe class ABEtherNetReader : IPLCDriver |
||||
|
{ |
||||
|
Eip_Connection* connection; |
||||
|
Eip_Session* session; |
||||
|
byte _rack = 1; |
||||
|
byte _slot; |
||||
|
string _ip; |
||||
|
|
||||
|
short _id; |
||||
|
public short ID |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _id; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public bool IsClosed |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return connection == null || session == null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public int PDU |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return 492; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int _timeOut = 1000; |
||||
|
public int TimeOut |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _timeOut; |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
_timeOut = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
string _name; |
||||
|
public string Name |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _name; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public string ServerName |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _ip; |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
_ip = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public byte Rack |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _rack; |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
_rack = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public byte Slot |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return _slot; |
||||
|
} |
||||
|
set |
||||
|
{ |
||||
|
_slot = value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ABEtherNetReader(IDataServer server, short id, string name) |
||||
|
{ |
||||
|
_id = id; |
||||
|
_server = server; |
||||
|
_name = name; |
||||
|
} |
||||
|
|
||||
|
public bool Connect() |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (session != null) Dispose(); |
||||
|
session = Tuxeip_Class.OpenSession(_ip); |
||||
|
byte[] path = new byte[] { _rack, _slot }; |
||||
|
if (session != null) |
||||
|
{ |
||||
|
int res = Tuxeip_Class._RegisterSession(session); |
||||
|
connection = Tuxeip_Class.ConnectPLCOverCNET(session, Plc_Type.LGX, path); |
||||
|
} |
||||
|
return (session != null && connection != null); |
||||
|
} |
||||
|
catch (Exception error) |
||||
|
{ |
||||
|
if (OnClose != null) |
||||
|
{ |
||||
|
OnClose(this, new ShutdownRequestEventArgs(error.Message)); |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
List<IGroup> _groups = new List<IGroup>(); |
||||
|
public IEnumerable<IGroup> Groups |
||||
|
{ |
||||
|
get { return _groups; } |
||||
|
} |
||||
|
|
||||
|
IDataServer _server; |
||||
|
public IDataServer Parent |
||||
|
{ |
||||
|
get { return _server; } |
||||
|
} |
||||
|
|
||||
|
public IGroup AddGroup(string name, short id, int updateRate, float deadBand, bool active) |
||||
|
{ |
||||
|
ABPLCGroup grp = new ABPLCGroup(id, name, updateRate, active, this); |
||||
|
_groups.Add(grp); |
||||
|
return grp; |
||||
|
} |
||||
|
|
||||
|
public bool RemoveGroup(IGroup grp) |
||||
|
{ |
||||
|
grp.IsActive = false; |
||||
|
return _groups.Remove(grp); |
||||
|
} |
||||
|
|
||||
|
public event ShutdownRequestEventHandler OnClose; |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
if (connection != null) |
||||
|
Tuxeip_Class._Forward_Close(connection); |
||||
|
if (session != null) |
||||
|
Tuxeip_Class._UnRegisterSession(session); |
||||
|
Tuxeip_Class.CloseSession(session); |
||||
|
Marshal.FreeCoTaskMem((IntPtr)connection); |
||||
|
Marshal.FreeCoTaskMem((IntPtr)session); |
||||
|
connection = null; |
||||
|
session = null; |
||||
|
} |
||||
|
|
||||
|
public string GetAddress(DeviceAddress address) |
||||
|
{ |
||||
|
return string.Concat(address.Area == ABAREA.N ? "N" : "F", address.DBNumber.ToString(), "[", address.Start.ToString(), "]", |
||||
|
address.VarType == DataType.BOOL ? "." + address.Bit.ToString() : "");//考虑对localData I/O信号的解析
|
||||
|
} |
||||
|
|
||||
|
public DeviceAddress GetDeviceAddress(string address) |
||||
|
{ |
||||
|
DeviceAddress addr = DeviceAddress.Empty;//考虑对localData I/O信号的解析
|
||||
|
if (!string.IsNullOrEmpty(address)) |
||||
|
{ |
||||
|
addr.Area = address[0] == 'N' ? ABAREA.N : ABAREA.F; |
||||
|
int index = address.IndexOf('['); |
||||
|
if (index > 0) |
||||
|
{ |
||||
|
ushort db; |
||||
|
ushort.TryParse(address.Substring(1, index - 1), out db); |
||||
|
addr.DBNumber = db; |
||||
|
int ind2 = address.IndexOf(']'); |
||||
|
if (ind2 > 0) |
||||
|
{ |
||||
|
int start; |
||||
|
int.TryParse(address.Substring(index + 1, ind2 - index - 1), out start); |
||||
|
addr.Start = start; |
||||
|
} |
||||
|
int dig = address.IndexOf('.'); |
||||
|
if (dig > 0) |
||||
|
{ |
||||
|
byte bit; |
||||
|
byte.TryParse(address.Substring(dig + 1), out bit); |
||||
|
addr.Bit = bit; |
||||
|
addr.VarType = DataType.BOOL; |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
ushort db; |
||||
|
ushort.TryParse(address.Substring(1), out db); |
||||
|
addr.DBNumber = db; |
||||
|
} |
||||
|
} |
||||
|
return addr; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public byte[] ReadBytes(DeviceAddress address, ushort size) |
||||
|
{ |
||||
|
byte[] result = new byte[size]; |
||||
|
float[] buffer = ReadFloatArray(address, (ushort)(size / 4)); |
||||
|
if (buffer != null) |
||||
|
{ |
||||
|
Buffer.BlockCopy(buffer, 0, result, 0, size); |
||||
|
return result; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public float[] ReadFloatArray(DeviceAddress address, ushort size) |
||||
|
{ |
||||
|
if (IsClosed) |
||||
|
return null; |
||||
|
else |
||||
|
{ |
||||
|
float[] buffer = new float[size]; address.VarType = DataType.FLOAT; var addr = GetAddress(address); |
||||
|
LGX_Read* data = Tuxeip_Class._ReadLgxData(session, connection, addr, size); |
||||
|
if (data != null && data->Varcount > 0) |
||||
|
{ |
||||
|
for (int i = 0; i < data->Varcount; i++) |
||||
|
{ |
||||
|
buffer[i] = Tuxeip_Class._GetLGXValueAsFloat(data, i); |
||||
|
} |
||||
|
data = null; |
||||
|
return buffer; |
||||
|
} |
||||
|
connection = null; |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ItemData<int> ReadInt32(DeviceAddress address) |
||||
|
{ |
||||
|
if (IsClosed) |
||||
|
return new ItemData<int>(0, 0, QUALITIES.QUALITY_NOT_CONNECTED); |
||||
|
else |
||||
|
{ |
||||
|
LGX_Read* data = Tuxeip_Class._ReadLgxData(session, connection, GetAddress(address), 1); |
||||
|
return new ItemData<int>(Tuxeip_Class._GetLGXValueAsInteger(data, 0), 0, QUALITIES.QUALITY_GOOD); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ItemData<short> ReadInt16(DeviceAddress address) |
||||
|
{ |
||||
|
if (IsClosed) |
||||
|
return new ItemData<short>(0, 0, QUALITIES.QUALITY_NOT_CONNECTED); |
||||
|
else |
||||
|
{ |
||||
|
LGX_Read* data = Tuxeip_Class._ReadLgxData(session, connection, GetAddress(address), 1); |
||||
|
return new ItemData<short>((short)Tuxeip_Class._GetLGXValueAsInteger(data, 0), 0, QUALITIES.QUALITY_GOOD); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ItemData<byte> ReadByte(DeviceAddress address) |
||||
|
{ |
||||
|
if (IsClosed) |
||||
|
return new ItemData<byte>(0, 0, QUALITIES.QUALITY_NOT_CONNECTED); |
||||
|
else |
||||
|
{ |
||||
|
LGX_Read* data = Tuxeip_Class._ReadLgxData(session, connection, GetAddress(address), 1); |
||||
|
return new ItemData<byte>((byte)Tuxeip_Class._GetLGXValueAsInteger(data, 0), 0, QUALITIES.QUALITY_GOOD); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ItemData<string> ReadString(DeviceAddress address, ushort size) |
||||
|
{ |
||||
|
if (IsClosed) |
||||
|
return new ItemData<string>(string.Empty, 0, QUALITIES.QUALITY_NOT_CONNECTED); |
||||
|
else |
||||
|
{ |
||||
|
byte[] buffer = ReadBytes(address, size); |
||||
|
if (buffer != null) |
||||
|
{ |
||||
|
return new ItemData<string>(Encoding.ASCII.GetString(buffer).Trim(), 0, QUALITIES.QUALITY_GOOD); |
||||
|
} |
||||
|
return new ItemData<string>(string.Empty, 0, QUALITIES.QUALITY_BAD); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ItemData<float> ReadFloat(DeviceAddress address) |
||||
|
{ |
||||
|
if (IsClosed) |
||||
|
return new ItemData<float>(0, 0, QUALITIES.QUALITY_NOT_CONNECTED); |
||||
|
else |
||||
|
{ |
||||
|
LGX_Read* data = Tuxeip_Class._ReadLgxData(session, connection, GetAddress(address), 1); |
||||
|
return new ItemData<float>(Tuxeip_Class._GetLGXValueAsFloat(data, 0), 0, QUALITIES.QUALITY_GOOD); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ItemData<bool> ReadBit(DeviceAddress address) |
||||
|
{ |
||||
|
if (IsClosed) |
||||
|
return new ItemData<bool>(false, 0, QUALITIES.QUALITY_NOT_CONNECTED); |
||||
|
else |
||||
|
{ |
||||
|
LGX_Read* data = Tuxeip_Class._ReadLgxData(session, connection, GetAddress(address), 1); |
||||
|
return new ItemData<bool>(Tuxeip_Class._GetLGXValueAsInteger(data, 0) > 0, 0, QUALITIES.QUALITY_GOOD); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ItemData<object> ReadValue(DeviceAddress address) |
||||
|
{ |
||||
|
return this.ReadValueEx(address); |
||||
|
} |
||||
|
|
||||
|
public unsafe int WriteBytes(DeviceAddress address, byte[] bit) |
||||
|
{ |
||||
|
if (IsClosed) return -1; |
||||
|
fixed (void* b = bit) |
||||
|
{ |
||||
|
return Tuxeip_Class._WriteLgxData(session, connection, GetAddress(address), LGX_Data_Type.LGX_BITARRAY, b, 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public int WriteBit(DeviceAddress address, bool bit) |
||||
|
{ |
||||
|
if (IsClosed) return -1; |
||||
|
return Tuxeip_Class._WriteLgxData(session, connection, GetAddress(address), LGX_Data_Type.LGX_BOOL, &bit, 1); |
||||
|
} |
||||
|
|
||||
|
public int WriteBits(DeviceAddress address, byte bits) |
||||
|
{ |
||||
|
if (IsClosed) return -1; |
||||
|
return Tuxeip_Class._WriteLgxData(session, connection, GetAddress(address), LGX_Data_Type.LGX_SINT, &bits, 1); |
||||
|
} |
||||
|
|
||||
|
public int WriteInt16(DeviceAddress address, short value) |
||||
|
{ |
||||
|
if (IsClosed) return -1; |
||||
|
return Tuxeip_Class._WriteLgxData(session, connection, GetAddress(address), LGX_Data_Type.LGX_INT, &value, 1); |
||||
|
} |
||||
|
|
||||
|
public int WriteInt32(DeviceAddress address, int value) |
||||
|
{ |
||||
|
if (IsClosed) return -1; |
||||
|
return Tuxeip_Class._WriteLgxData(session, connection, GetAddress(address), LGX_Data_Type.LGX_DINT, &value, 1); |
||||
|
} |
||||
|
|
||||
|
public int WriteFloat(DeviceAddress address, float value) |
||||
|
{ |
||||
|
if (IsClosed) return -1; |
||||
|
return Tuxeip_Class._WriteLgxData(session, connection, GetAddress(address), LGX_Data_Type.LGX_REAL, &value, 1); |
||||
|
} |
||||
|
|
||||
|
public int WriteString(DeviceAddress address, string str) |
||||
|
{ |
||||
|
byte[] b = Encoding.ASCII.GetBytes(str); |
||||
|
return WriteBytes(address, b); |
||||
|
} |
||||
|
|
||||
|
public int WriteValue(DeviceAddress address, object value) |
||||
|
{ |
||||
|
return this.WriteValueEx(address, value); |
||||
|
} |
||||
|
|
||||
|
public ItemData<uint> ReadUInt32(DeviceAddress address) |
||||
|
{ |
||||
|
if (IsClosed) |
||||
|
return new ItemData<uint>(0, 0, QUALITIES.QUALITY_NOT_CONNECTED); |
||||
|
else |
||||
|
{ |
||||
|
LGX_Read* data = Tuxeip_Class._ReadLgxData(session, connection, GetAddress(address), 1); |
||||
|
return new ItemData<uint>((uint)Tuxeip_Class._GetLGXValueAsInteger(data, 0), 0, QUALITIES.QUALITY_GOOD); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public ItemData<ushort> ReadUInt16(DeviceAddress address) |
||||
|
{ |
||||
|
if (IsClosed) |
||||
|
return new ItemData<ushort>(0, 0, QUALITIES.QUALITY_NOT_CONNECTED); |
||||
|
else |
||||
|
{ |
||||
|
LGX_Read* data = Tuxeip_Class._ReadLgxData(session, connection, GetAddress(address), 1); |
||||
|
return new ItemData<ushort>((ushort)Tuxeip_Class._GetLGXValueAsInteger(data, 0), 0, QUALITIES.QUALITY_GOOD); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public int WriteUInt16(DeviceAddress address, ushort value) |
||||
|
{ |
||||
|
if (IsClosed) return -1; |
||||
|
return Tuxeip_Class._WriteLgxData(session, connection, GetAddress(address), LGX_Data_Type.LGX_INT, &value, 1); |
||||
|
} |
||||
|
|
||||
|
public int WriteUInt32(DeviceAddress address, uint value) |
||||
|
{ |
||||
|
if (IsClosed) return -1; |
||||
|
return Tuxeip_Class._WriteLgxData(session, connection, GetAddress(address), LGX_Data_Type.LGX_DINT, &value, 1); |
||||
|
} |
||||
|
|
||||
|
public int Limit |
||||
|
{ |
||||
|
get { return 122; } |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public sealed class ABPLCGroup : PLCGroup |
||||
|
{ |
||||
|
public ABPLCGroup(short id, string name, int updateRate, bool active, ABEtherNetReader plcReader) |
||||
|
{ |
||||
|
this._id = id; |
||||
|
this._name = name; |
||||
|
this._updateRate = updateRate; |
||||
|
this._isActive = active; |
||||
|
this._plcReader = plcReader; |
||||
|
this._server = _plcReader.Parent; |
||||
|
this._changedList = new List<int>(); |
||||
|
this._timer = new Timer(); |
||||
|
this._cacheReader = new FloatCacheReader(); |
||||
|
} |
||||
|
|
||||
|
protected override void Poll() |
||||
|
{ |
||||
|
float[] cache = (float[])_cacheReader.Cache; |
||||
|
int offset = 0; |
||||
|
foreach (PDUArea area in _rangeList) |
||||
|
{ |
||||
|
float[] prcv = ((ABEtherNetReader)_plcReader).ReadFloatArray(area.Start, (ushort)area.Len);//从PLC读取数据
|
||||
|
if (prcv == null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
int len = prcv.Length; |
||||
|
int index = area.StartIndex;//index指向_items中的Tag元数据
|
||||
|
int count = index + area.Count; |
||||
|
while (index < count) |
||||
|
{ |
||||
|
DeviceAddress addr = _items[index].Address; |
||||
|
int iInt = addr.CacheIndex; |
||||
|
int iInt1 = iInt - offset; |
||||
|
if (addr.VarType == DataType.BOOL) |
||||
|
{ |
||||
|
int tmp = (int)prcv[iInt1] ^ (int)cache[iInt]; |
||||
|
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 <= 4) |
||||
|
{ |
||||
|
if (prcv[iInt1] != cache[iInt]) _changedList.Add(index); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
int size = addr.DataSize / 4; |
||||
|
for (int i = 0; i < size; i++) |
||||
|
{ |
||||
|
if (prcv[iInt1 + i] != cache[iInt + i]) |
||||
|
{ |
||||
|
_changedList.Add(index); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
index++; |
||||
|
} |
||||
|
} |
||||
|
for (int j = 0; j < len; j++) |
||||
|
{ |
||||
|
cache[j + offset] = prcv[j]; |
||||
|
}//将PLC读取的数据写入到CacheReader中
|
||||
|
offset += len; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class ABAREA |
||||
|
{ |
||||
|
public const int N = 0; |
||||
|
public const int F = 1; |
||||
|
public const int I = 2; |
||||
|
public const int O = 3; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,126 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<PropertyGroup> |
||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||
|
<ProductVersion>8.0.30703</ProductVersion> |
||||
|
<SchemaVersion>2.0</SchemaVersion> |
||||
|
<ProjectGuid>{02EA8F3A-29F0-4E11-B4F6-3BF87242D99F}</ProjectGuid> |
||||
|
<OutputType>Library</OutputType> |
||||
|
<AppDesignerFolder>Properties</AppDesignerFolder> |
||||
|
<RootNamespace>ABPLCReader</RootNamespace> |
||||
|
<AssemblyName>ABPLCReader</AssemblyName> |
||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
||||
|
<FileAlignment>512</FileAlignment> |
||||
|
<TargetFrameworkProfile>Client</TargetFrameworkProfile> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||
|
<DebugSymbols>true</DebugSymbols> |
||||
|
<DebugType>full</DebugType> |
||||
|
<Optimize>false</Optimize> |
||||
|
<OutputPath>bin\Debug\</OutputPath> |
||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
|
<ErrorReport>prompt</ErrorReport> |
||||
|
<WarningLevel>4</WarningLevel> |
||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||
|
<DebugType>pdbonly</DebugType> |
||||
|
<Optimize>true</Optimize> |
||||
|
<OutputPath>bin\Release\</OutputPath> |
||||
|
<DefineConstants>TRACE</DefineConstants> |
||||
|
<ErrorReport>prompt</ErrorReport> |
||||
|
<WarningLevel>4</WarningLevel> |
||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> |
||||
|
<DebugSymbols>true</DebugSymbols> |
||||
|
<OutputPath>bin\x64\Debug\</OutputPath> |
||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
|
<DebugType>full</DebugType> |
||||
|
<PlatformTarget>x64</PlatformTarget> |
||||
|
<CodeAnalysisLogFile>bin\Debug\ABPLCReader.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> |
||||
|
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> |
||||
|
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> |
||||
|
<ErrorReport>prompt</ErrorReport> |
||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> |
||||
|
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> |
||||
|
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets> |
||||
|
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> |
||||
|
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> |
||||
|
<OutputPath>bin\x64\Release\</OutputPath> |
||||
|
<DefineConstants>TRACE</DefineConstants> |
||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
||||
|
<Optimize>true</Optimize> |
||||
|
<DebugType>pdbonly</DebugType> |
||||
|
<PlatformTarget>x64</PlatformTarget> |
||||
|
<CodeAnalysisLogFile>bin\Release\ABPLCReader.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> |
||||
|
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> |
||||
|
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> |
||||
|
<ErrorReport>prompt</ErrorReport> |
||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> |
||||
|
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> |
||||
|
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets> |
||||
|
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> |
||||
|
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|Itanium'"> |
||||
|
<DebugSymbols>true</DebugSymbols> |
||||
|
<OutputPath>bin\Itanium\Debug\</OutputPath> |
||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
||||
|
<DebugType>full</DebugType> |
||||
|
<PlatformTarget>Itanium</PlatformTarget> |
||||
|
<CodeAnalysisLogFile>bin\Debug\ABPLCReader.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> |
||||
|
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> |
||||
|
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> |
||||
|
<ErrorReport>prompt</ErrorReport> |
||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> |
||||
|
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> |
||||
|
<CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets> |
||||
|
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> |
||||
|
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|Itanium'"> |
||||
|
<OutputPath>bin\Release\</OutputPath> |
||||
|
<DefineConstants>TRACE</DefineConstants> |
||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
||||
|
<Optimize>true</Optimize> |
||||
|
<DebugType>pdbonly</DebugType> |
||||
|
<PlatformTarget>AnyCPU</PlatformTarget> |
||||
|
<CodeAnalysisLogFile>bin\Release\ABPLCReader.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> |
||||
|
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> |
||||
|
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> |
||||
|
<ErrorReport>prompt</ErrorReport> |
||||
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> |
||||
|
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> |
||||
|
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets> |
||||
|
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> |
||||
|
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules> |
||||
|
</PropertyGroup> |
||||
|
<ItemGroup> |
||||
|
<Reference Include="System" /> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<Compile Include="ABPLCDriver.cs" /> |
||||
|
<Compile Include="Properties\AssemblyInfo.cs" /> |
||||
|
<Compile Include="Tuxeip_Class.cs" /> |
||||
|
<Compile Include="Tuxeip_Struct.cs" /> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\DataService\DataService.csproj"> |
||||
|
<Project>{8965e389-6466-4b30-bd43-83c909044637}</Project> |
||||
|
<Name>DataService</Name> |
||||
|
</ProjectReference> |
||||
|
</ItemGroup> |
||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
||||
|
Other similar extension points exist, see Microsoft.Common.targets. |
||||
|
<Target Name="BeforeBuild"> |
||||
|
</Target> |
||||
|
<Target Name="AfterBuild"> |
||||
|
</Target> |
||||
|
--> |
||||
|
</Project> |
||||
Binary file not shown.
@ -0,0 +1,36 @@ |
|||||
|
using System.Reflection; |
||||
|
using System.Runtime.CompilerServices; |
||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
// General Information about an assembly is controlled through the following
|
||||
|
// set of attributes. Change these attribute values to modify the information
|
||||
|
// associated with an assembly.
|
||||
|
[assembly: AssemblyTitle("ABPLCReader")] |
||||
|
[assembly: AssemblyDescription("")] |
||||
|
[assembly: AssemblyConfiguration("")] |
||||
|
[assembly: AssemblyCompany("")] |
||||
|
[assembly: AssemblyProduct("ABPLCReader")] |
||||
|
[assembly: AssemblyCopyright("Copyright © 2012")] |
||||
|
[assembly: AssemblyTrademark("")] |
||||
|
[assembly: AssemblyCulture("")] |
||||
|
|
||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
|
// to COM components. If you need to access a type in this assembly from
|
||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||
|
[assembly: ComVisible(false)] |
||||
|
|
||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
|
[assembly: Guid("dced3a2e-feef-4144-bcad-e2ace205c774")] |
||||
|
|
||||
|
// Version information for an assembly consists of the following four values:
|
||||
|
//
|
||||
|
// Major Version
|
||||
|
// Minor Version
|
||||
|
// Build Number
|
||||
|
// Revision
|
||||
|
//
|
||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
|
// by using the '*' as shown below:
|
||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||
|
[assembly: AssemblyVersion("1.0.0.0")] |
||||
|
[assembly: AssemblyFileVersion("1.0.0.0")] |
||||
@ -0,0 +1,162 @@ |
|||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
namespace Tuxeip |
||||
|
{ |
||||
|
public unsafe class Tuxeip_Class |
||||
|
{ |
||||
|
public const int MAX_MSG_LEN = 1024; // a verifier
|
||||
|
|
||||
|
public const int EIP_PORT = 0xAF12;//44818
|
||||
|
public const int ENCAP_PROTOCOL = 0x0001; |
||||
|
|
||||
|
/* Ethernet IP commands */ |
||||
|
public const int EIP_NOP = 0x0000; |
||||
|
public const int EIP_LISTTARGETS = 0x0001; // Reserved for legacy RA
|
||||
|
public const int EIP_LISTSERVICES = 0x0004; |
||||
|
public const int EIP_LISTIDENTITY = 0x0063; |
||||
|
public const int EIP_LISTINTERFACES = 0x0064; |
||||
|
public const int EIP_REGISTERSESSION = 0x0065; |
||||
|
public const int EIP_UNREGISTERSESSION = 0x0066; |
||||
|
public const int EIP_SENDRRDATA = 0x006F; |
||||
|
public const int EIP_SENDUNITDATA = 0x0070; |
||||
|
public const int EIP_INDICATESTATUS = 0x0072; |
||||
|
public const int EIP_CANCEL = 0x0073; |
||||
|
|
||||
|
// Ethernet IP status code
|
||||
|
public const int EIP_SUCCESS = 0x0000; |
||||
|
public const int EIP_INVALID_COMMAND = 0x0001; |
||||
|
public const int EIP_MEMORY = 0x0002; |
||||
|
public const int EIP_INCORRECT_DATA = 0x0003; |
||||
|
public const int EIP_INVALID_SESSION_HANDLE = 0x0064; |
||||
|
public const int EIP_INVALID_LENGTH = 0x0065; |
||||
|
public const int EIP_UNSUPPORTED_PROTOCOL = 0x0069; |
||||
|
|
||||
|
// Ethernet IP Services Class
|
||||
|
public const int EIP_SC_COMMUNICATION = 0x0100; |
||||
|
public const int EIP_VERSION = 0x01; |
||||
|
public const int CIP_DEFAULT_TIMEOUT = 1000; |
||||
|
|
||||
|
private const ushort _OriginatorVendorID = 0xFFFE; |
||||
|
private const uint _OriginatorSerialNumber = 0x12345678; |
||||
|
private const byte _Priority = 0x07; |
||||
|
private const sbyte _TimeOut_Ticks = 0x3f; |
||||
|
private const short _Parameters = 0x43f8, _TO_Parameters = 0x43f8; |
||||
|
private const byte _Transport = 0xa3; |
||||
|
private const sbyte _TimeOutMultiplier = 0x01; |
||||
|
|
||||
|
const string PATH = @"tuxeipAB.dll"; |
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
private static extern Eip_Session* _OpenSession(string serveur, int port, int buffer_len, int timeout); |
||||
|
public static Eip_Session* OpenSession(string serveur) |
||||
|
{ |
||||
|
return _OpenSession(serveur, EIP_PORT, MAX_MSG_LEN, CIP_DEFAULT_TIMEOUT); |
||||
|
} |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern void CloseSession(Eip_Session* session); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern int _RegisterSession(Eip_Session* session); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern int _UnRegisterSession(Eip_Session* session); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
private static extern Eip_Connection* _ConnectPLCOverCNET( |
||||
|
Eip_Session* session, |
||||
|
Plc_Type Plc, |
||||
|
byte Priority, |
||||
|
sbyte TimeOut_Ticks, |
||||
|
uint TO_ConnID, //originator's CIP consumed session ID
|
||||
|
ushort ConnSerialNumber,// session serial number
|
||||
|
ushort OriginatorVendorID, |
||||
|
uint OriginatorSerialNumber, |
||||
|
sbyte TimeOutMultiplier, |
||||
|
uint RPI,// originator to target packet rate in msec
|
||||
|
byte Transport, |
||||
|
byte[] path, byte pathsize); |
||||
|
public static Eip_Connection* ConnectPLCOverCNET(Eip_Session* session, Plc_Type Plc, byte[] path) |
||||
|
{ |
||||
|
return _ConnectPLCOverCNET(session, Plc, _Priority, _TimeOut_Ticks, 0x12345678, 0x6789, |
||||
|
_OriginatorVendorID, _OriginatorSerialNumber, _TimeOutMultiplier, 5000, _Transport, path, (byte)path.Length); |
||||
|
} |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern Eip_Connection* _ConnectPLCOverDHP( |
||||
|
Eip_Session* session, |
||||
|
Plc_Type Plc, |
||||
|
byte Priority, |
||||
|
sbyte TimeOut_Ticks, |
||||
|
uint TO_ConnID, //originator's CIP consumed session ID
|
||||
|
ushort ConnSerialNumber,// session serial number
|
||||
|
ushort OriginatorVendorID, |
||||
|
uint OriginatorSerialNumber, |
||||
|
sbyte TimeOutMultiplier, |
||||
|
uint RPI,// originator to target packet rate in msec
|
||||
|
byte Transport, |
||||
|
DHP_Channel channel, |
||||
|
byte[] path, byte pathsize); |
||||
|
public static Eip_Connection* ConnectPLCOverDHP(Eip_Session* session, Plc_Type Plc, DHP_Channel channel, byte[] path) |
||||
|
{ |
||||
|
return _ConnectPLCOverDHP(session, Plc, _Priority, _TimeOut_Ticks, 0x12345678, 0x6789, |
||||
|
_OriginatorVendorID, _OriginatorSerialNumber, _TimeOutMultiplier, 5000, _Transport, channel, path, (byte)path.Length); |
||||
|
} |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern PLC_Read* _ReadPLCData( |
||||
|
Eip_Session* session, |
||||
|
Eip_Connection* connection, |
||||
|
DHP_Header* dhp, |
||||
|
byte* routepath, byte routepathsize, |
||||
|
Plc_Type type, short tns, |
||||
|
string address, short number); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern int _WritePLCData( |
||||
|
Eip_Session* session, |
||||
|
Eip_Connection* connection, |
||||
|
DHP_Header* dhp, |
||||
|
byte* routepath, byte routepathsize, |
||||
|
Plc_Type type, short tns, |
||||
|
string address, |
||||
|
PLC_Data_Type datatype, |
||||
|
void* data, |
||||
|
short number); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern int _PCCC_GetValueAsBoolean(PLC_Read* reply, int index); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern float _PCCC_GetValueAsFloat(PLC_Read* reply, int index); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern int _PCCC_GetValueAsInteger(PLC_Read* reply, int index); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern int _GetLGXValueAsInteger(LGX_Read* reply, int index); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern float _GetLGXValueAsFloat(LGX_Read* reply, int index); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern int _Forward_Close(Eip_Connection* connection); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern LGX_Read* _ReadLgxData( |
||||
|
Eip_Session* session, |
||||
|
Eip_Connection* connection, |
||||
|
string adress, |
||||
|
ushort number); |
||||
|
|
||||
|
[DllImport(PATH, CallingConvention = CallingConvention.Cdecl)] |
||||
|
public static extern int _WriteLgxData( |
||||
|
Eip_Session* session, |
||||
|
Eip_Connection* connection, |
||||
|
string adress, |
||||
|
LGX_Data_Type datatype, |
||||
|
void* data, |
||||
|
//int datasize,
|
||||
|
short number); |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,115 @@ |
|||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
namespace Tuxeip |
||||
|
{ |
||||
|
public enum Plc_Type { Unknow, PLC5, SLC500, LGX } |
||||
|
|
||||
|
public enum DHP_Channel { Channel_A = 0x01, Channel_B } |
||||
|
|
||||
|
public enum Data_Type { UNKNOW, BIT, SINT, TUXINT, DINT, REAL, TIMER, COUNTER } |
||||
|
|
||||
|
public enum PLC_Data_Type |
||||
|
{ |
||||
|
PLC_BIT = 1, |
||||
|
PLC_BIT_STRING, |
||||
|
PLC_BYTE_STRING, |
||||
|
PLC_INTEGER, |
||||
|
PLC_TIMER, |
||||
|
PLC_COUNTER, |
||||
|
PLC_CONTROL, |
||||
|
PLC_FLOATING, |
||||
|
PLC_ARRAY, |
||||
|
PLC_ADRESS = 15, |
||||
|
PLC_BCD |
||||
|
} ; |
||||
|
|
||||
|
public enum LGX_Data_Type |
||||
|
{ |
||||
|
LGX_BOOL = 0xC1, |
||||
|
LGX_BITARRAY = 0xD3, |
||||
|
LGX_SINT = 0xC2, |
||||
|
LGX_INT = 0xC3, |
||||
|
LGX_DINT = 0xC4, |
||||
|
LGX_REAL = 0xCA |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
[StructLayout(LayoutKind.Explicit)] |
||||
|
public unsafe struct Eip_Session |
||||
|
{ |
||||
|
[FieldOffset(0)] |
||||
|
int sock; |
||||
|
[FieldOffset(4)] |
||||
|
uint Session_Handle; |
||||
|
[FieldOffset(8)] |
||||
|
uint Sender_ContextL; |
||||
|
[FieldOffset(12)] |
||||
|
uint Sender_ContextH; |
||||
|
[FieldOffset(16)] |
||||
|
int timeout; |
||||
|
[FieldOffset(20)] |
||||
|
int References; |
||||
|
[FieldOffset(24)] |
||||
|
void* Data; |
||||
|
} |
||||
|
|
||||
|
[StructLayout(LayoutKind.Explicit)] |
||||
|
public unsafe struct Eip_Connection |
||||
|
{ |
||||
|
/* Connected send parameters */ |
||||
|
[FieldOffset(0)] |
||||
|
Eip_Session* Session; |
||||
|
[FieldOffset(4)] |
||||
|
int References; |
||||
|
[FieldOffset(8)] |
||||
|
void* Data; |
||||
|
[FieldOffset(12)] |
||||
|
ushort ConnectionSerialNumber; |
||||
|
[FieldOffset(14)] |
||||
|
ushort OriginatorVendorID; |
||||
|
[FieldOffset(16)] |
||||
|
uint OriginatorSerialNumber; |
||||
|
|
||||
|
[FieldOffset(20)] |
||||
|
uint OT_ConnID; //originator's CIP Produced session ID
|
||||
|
|
||||
|
[FieldOffset(24)] |
||||
|
uint TO_ConnID; //originator's CIP consumed session ID
|
||||
|
[FieldOffset(28)] |
||||
|
short packet; |
||||
|
[FieldOffset(30)] |
||||
|
byte Path_size;//
|
||||
|
//BYTE Path[0];
|
||||
|
} |
||||
|
|
||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)] |
||||
|
public struct PLC_Read |
||||
|
{ |
||||
|
public PLC_Data_Type type; |
||||
|
public int Varcount; |
||||
|
public int totalsize; |
||||
|
public int elementsize; |
||||
|
public uint mask; |
||||
|
} |
||||
|
|
||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)] |
||||
|
public struct DHP_Header |
||||
|
{ |
||||
|
public ushort Dest_link; |
||||
|
public ushort Dest_adress; |
||||
|
public ushort Src_link; |
||||
|
public ushort Src_adress; |
||||
|
//BYTE data; // the PCCC request
|
||||
|
} |
||||
|
|
||||
|
[StructLayout(LayoutKind.Sequential, Pack = 4)] |
||||
|
public struct LGX_Read |
||||
|
{ |
||||
|
public LGX_Data_Type type; |
||||
|
public int Varcount; |
||||
|
public int totalsize; |
||||
|
public int elementsize; |
||||
|
public uint mask; |
||||
|
} |
||||
|
} |
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue