S7.NET Testability Updates

Removed the Controls project and existing Test projects. Added new Test
project and references to NUnit and Should projects for testing.
Extracted IPlc interface to help test projects that reference this
library. Also implemented the IDisposable interface on the Plc object so
that references to mSocket would be cleaned up appropriately when the
object is blown away.
This commit is contained in:
Derek Heiser
2013-02-09 10:17:47 -06:00
parent 03e3c8abc3
commit e65c0eed25
31 changed files with 13175 additions and 0 deletions

View File

@@ -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("S7.Net.Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("S7.Net.Test")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[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("14c9af75-ff21-41a3-9b55-32b081e948f3")]
// 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")]

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D34F7AF6-19DA-4AE6-9BB0-6666970F6838}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>S7.Net.Test</RootNamespace>
<AssemblyName>S7.Net.Test</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</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>
</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>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Should">
<HintPath>..\packages\Should.1.1.12.0\lib\Should.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</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>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="2.6.2" targetFramework="net45" />
<package id="Should" version="1.1.12.0" targetFramework="net45" />
</packages>

167
S7.Net/Conversion.cs Normal file
View File

@@ -0,0 +1,167 @@
using System;
using System.Linq;
namespace S7
{
public static class Conversion
{
public static int BinStringToInt32(this string txt)
{
int cnt = 0;
int ret = 0;
for (cnt = txt.Length - 1; cnt >= 0; cnt += -1)
{
if (int.Parse(txt.Substring(cnt, 1)) == 1)
{
ret += (int)(Math.Pow(2, (txt.Length - 1 - cnt)));
}
}
return ret;
}
public static byte? BinStringToByte(this string txt)
{
int cnt = 0;
int ret = 0;
if (txt.Length == 8)
{
for (cnt = 7; cnt >= 0; cnt += -1)
{
if (int.Parse(txt.Substring(cnt, 1)) == 1)
{
ret += (int)(Math.Pow(2, (txt.Length - 1 - cnt)));
}
}
return (byte)ret;
}
return null;
}
public static string ValToBinString(this object value)
{
int cnt = 0;
int cnt2 = 0;
int x = 0;
string txt = "";
long longValue = 0;
try
{
if (value.GetType().Name.IndexOf("[]") < 0)
{
// ist nur ein Wert
switch (value.GetType().Name)
{
case "Byte":
x = 7;
longValue = (long)((byte)value);
break;
case "Int16":
x = 15;
longValue = (long)((Int16)value);
break;
case "Int32":
x = 31;
longValue = (long)((Int32)value);
break;
case "Int64":
x = 63;
longValue = (long)((Int64)value);
break;
default:
throw new Exception();
}
for (cnt = x; cnt >= 0; cnt += -1)
{
if (((Int64)longValue & (Int64)Math.Pow(2, cnt)) > 0)
txt += "1";
else
txt += "0";
}
}
else
{
// ist ein Array
switch (value.GetType().Name)
{
case "Byte[]":
x = 7;
byte[] ByteArr = (byte[])value;
for (cnt2 = 0; cnt2 <= ByteArr.Length - 1; cnt2++)
{
for (cnt = x; cnt >= 0; cnt += -1)
if ((ByteArr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
}
break;
case "Int16[]":
x = 15;
Int16[] Int16Arr = (Int16[])value;
for (cnt2 = 0; cnt2 <= Int16Arr.Length - 1; cnt2++)
{
for (cnt = x; cnt >= 0; cnt += -1)
if ((Int16Arr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
}
break;
case "Int32[]":
x = 31;
Int32[] Int32Arr = (Int32[])value;
for (cnt2 = 0; cnt2 <= Int32Arr.Length - 1; cnt2++)
{
for (cnt = x; cnt >= 0; cnt += -1)
if ((Int32Arr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
}
break;
case "Int64[]":
x = 63;
byte[] Int64Arr = (byte[])value;
for (cnt2 = 0; cnt2 <= Int64Arr.Length - 1; cnt2++)
{
for (cnt = x; cnt >= 0; cnt += -1)
if ((Int64Arr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
}
break;
default:
throw new Exception();
}
}
return txt;
}
catch
{
return "";
}
}
public static int ByteToInt16(this byte[] data, int offset)
{
byte[] bytes = data.Skip(offset).Take(2).ToArray();
Array.Reverse(bytes);
return BitConverter.ToInt16(bytes, 0);
}
public static int ByteToInt32(this byte[] data, int offset)
{
byte[] bytes = data.Skip(offset).Take(4).ToArray();
Array.Reverse(bytes);
return BitConverter.ToInt32(bytes, 0);
}
public static float ByteToFloat(this byte[] data, int offset)
{
byte[] bytes = data.Skip(offset).Take(4).ToArray();
Array.Reverse(bytes);
return BitConverter.ToSingle(bytes, 0);
}
public static bool SelectBit(this byte data, int bitPosition)
{
int mask = 1 << bitPosition;
int result = data & mask;
return (result != 0);
}
}
}

54
S7.Net/Enums.cs Normal file
View File

@@ -0,0 +1,54 @@
namespace S7
{
#region CPU_Type
public enum CPU_Type
{
S7200 = 0,
S7300 = 10,
S7400 = 20
}
#endregion
#region Error Codes
public enum ErrorCode
{
NoError = 0,
WrongCPU_Type = 1,
ConnectionError = 2,
IPAdressNotAvailable,
WrongVarFormat = 10,
WrongNumberReceivedBytes = 11,
SendData = 20,
ReadData = 30,
WriteData = 50
}
#endregion
#region DataType
public enum DataType
{
Input = 129,
Output = 130,
Marker = 131,
DataBlock = 132,
Timer = 29,
Counter = 28
}
#endregion
#region VarType
public enum VarType
{
Bit,
Byte,
Word,
DWord,
Int,
DInt,
Real,
String,
Timer,
Counter
}
#endregion
}

26
S7.Net/Interfaces/IPLC.cs Normal file
View File

@@ -0,0 +1,26 @@
using System;
namespace S7
{
public interface IPlc : IDisposable
{
string IP { get; set; }
bool IsConnected { get; }
CPU_Type CPU { get; set; }
Int16 Rack { get; set; }
Int16 Slot { get; set; }
string Name { get; set; }
object Tag { get; set; }
bool IsAvailable { get; }
ErrorCode Open();
void Close();
byte[] ReadBytes(DataType DataType, int DB, int StartByteAdr, int count);
object Read(DataType DataType, int DB, int StartByteAdr, VarType VarType, int VarCount);
object Read(string variable);
object ReadStruct(Type structType, int DB);
ErrorCode WriteBytes(DataType DataType, int DB, int StartByteAdr, byte[] value);
object Write(DataType DataType, int DB, int StartByteAdr, object value);
object Write(string variable, object value);
ErrorCode WriteStruct(object structValue, int DB);
}
}

777
S7.Net/PLC.cs Normal file
View File

@@ -0,0 +1,777 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
namespace S7
{
public class Plc : IPlc
{
// public properties
public string IP
{ get; set; }
public CPU_Type CPU
{ get; set; }
public Int16 Rack
{ get; set; }
public Int16 Slot
{ get; set; }
public string Name
{ get; set; }
public object Tag
{ get; set; }
public bool IsAvailable
{
get
{
Ping ping = new Ping();
PingReply result = ping.Send(IP);
if (result.Status == IPStatus.Success)
return true;
else
return false;
}
}
public bool IsConnected { get; private set; }
public ErrorCode lastErrorCode = 0;
public string lastErrorString;
public int LastReadTime = 0;
public int LastWriteTime = 0;
private Socket mSocket;
public Plc() : this(CPU_Type.S7400, "localhost", 0, 2) { }
public Plc(CPU_Type cpu, string ip, Int16 rack, Int16 slot, string name = "", object tag = null)
{
IsConnected = false;
IP = ip;
CPU = cpu;
Rack = rack;
Slot = slot;
Name = name;
Tag = tag;
}
#region Connection (Open, Close)
public ErrorCode Open()
{
byte[] bReceive = new byte[256];
try {
// check if available
Ping p = new Ping();
PingReply pingReplay = p.Send(IP);
if (pingReplay.Status != IPStatus.Success)
throw new Exception();
}
catch
{
lastErrorCode = ErrorCode.IPAdressNotAvailable;
lastErrorString = "Destination IP-Address '" + IP + "' is not available!";
return lastErrorCode;
}
try {
// open the channel
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1000);
mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1000);
IPEndPoint _server = new IPEndPoint(new IPAddress(IPToByteArray(IP)), 102);
mSocket.Connect(_server);
}
catch (Exception ex) {
lastErrorCode = ErrorCode.ConnectionError;
lastErrorString = ex.Message;
return ErrorCode.ConnectionError;
}
try {
byte[] bSend1 = { 3, 0, 0, 22, 17, 224, 0, 0, 0, 46,
0, 193, 2, 1, 0, 194, 2, 3, 0, 192,
1, 9 };
switch (CPU) {
case CPU_Type.S7200:
//S7200: Chr(193) & Chr(2) & Chr(16) & Chr(0) 'Eigener Tsap
bSend1[11] = 193;
bSend1[12] = 2;
bSend1[13] = 16;
bSend1[14] = 0;
//S7200: Chr(194) & Chr(2) & Chr(16) & Chr(0) 'Fremder Tsap
bSend1[15] = 194;
bSend1[16] = 2;
bSend1[17] = 16;
bSend1[18] = 0;
break;
case CPU_Type.S7300:
//S7300: Chr(193) & Chr(2) & Chr(1) & Chr(0) 'Eigener Tsap
bSend1[11] = 193;
bSend1[12] = 2;
bSend1[13] = 1;
bSend1[14] = 0;
//S7300: Chr(194) & Chr(2) & Chr(3) & Chr(2) 'Fremder Tsap
bSend1[15] = 194;
bSend1[16] = 2;
bSend1[17] = 3;
bSend1[18] = (byte)(Rack * 2 * 16 + Slot);
break;
case CPU_Type.S7400:
//S7400: Chr(193) & Chr(2) & Chr(1) & Chr(0) 'Eigener Tsap
bSend1[11] = 193;
bSend1[12] = 2;
bSend1[13] = 1;
bSend1[14] = 0;
//S7400: Chr(194) & Chr(2) & Chr(3) & Chr(3) 'Fremder Tsap
bSend1[15] = 194;
bSend1[16] = 2;
bSend1[17] = 3;
bSend1[18] = (byte)(Rack * 2 * 16 + Slot);
break;
default:
return ErrorCode.WrongCPU_Type;
}
mSocket.Send(bSend1, 22, SocketFlags.None);
if (mSocket.Receive(bReceive, 22, SocketFlags.None) != 22) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
byte[] bsend2 = { 3, 0, 0, 25, 2, 240, 128, 50, 1, 0,
0, 255, 255, 0, 8, 0, 0, 240, 0, 0,
3, 0, 3, 1, 0 };
mSocket.Send(bsend2, 25, SocketFlags.None);
if (mSocket.Receive(bReceive, 27, SocketFlags.None) != 27) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
IsConnected = true;
}
catch
{
lastErrorCode = ErrorCode.ConnectionError;
lastErrorString = "Couldn't establish the connection!";
IsConnected = false;
return ErrorCode.ConnectionError;
}
return ErrorCode.NoError;
// ok
}
public void Close()
{
if (mSocket != null && mSocket.Connected) {
mSocket.Close();
IsConnected = false;
}
}
private byte[] IPToByteArray(string ip)
{
byte[] v = new byte[4];
string txt = ip;
string txt2 = null;
try
{
txt2 = txt.Substring(0, txt.IndexOf("."));
v[0] = byte.Parse(txt2);
txt = txt.Substring(txt2.Length + 1);
txt2 = txt.Substring(0, txt.IndexOf("."));
v[1] = byte.Parse(txt2);
txt = txt.Substring(txt2.Length + 1);
txt2 = txt.Substring(0, txt.IndexOf("."));
v[2] = byte.Parse(txt2);
txt = txt.Substring(txt2.Length + 1);
v[3] = byte.Parse(txt);
return v;
}
catch
{
v[0] = 0;
v[1] = 0;
v[2] = 0;
v[3] = 0;
return v;
}
}
#endregion
#region ReadBytes(DataType DataType, int DB, int StartByteAdr, int count)
public byte[] ReadBytes(DataType DataType, int DB, int StartByteAdr, int count)
{
byte[] bytes = new byte[count];
try
{
// first create the header
int packageSize = 31;
Types.ByteArray package = new Types.ByteArray(packageSize);
package.Add(new byte[] { 0x03, 0x00, 0x00 });
package.Add((byte)packageSize);
package.Add(new byte[] { 0x02, 0xf0, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x00, 0x00, 0x04, 0x01, 0x12,
0x0a, 0x10});
// package.Add(0x02); // datenart
switch (DataType)
{
case DataType.Timer:
case DataType.Counter:
package.Add((byte)DataType);
break;
default:
package.Add(0x02);
break;
}
package.Add(Types.Word.ToByteArray((ushort)(count)));
package.Add(Types.Word.ToByteArray((ushort)(DB)));
package.Add((byte)DataType);
package.Add((byte)0);
switch (DataType)
{
case DataType.Timer:
case DataType.Counter:
package.Add(Types.Word.ToByteArray((ushort)(StartByteAdr)));
break;
default:
package.Add(Types.Word.ToByteArray((ushort)((StartByteAdr) * 8)));
break;
}
mSocket.Send(package.array, package.array.Length, SocketFlags.None);
byte[] bReceive = new byte[512];
int numReceived = mSocket.Receive(bReceive, 512, SocketFlags.None);
if (bReceive[21] != 0xff) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
for (int cnt = 0; cnt < count; cnt++)
bytes[cnt] = bReceive[cnt + 25];
return bytes;
}
catch
{
lastErrorCode = ErrorCode.WriteData;
lastErrorString = "";
return null;
}
}
#endregion
#region Read(DataType DataType, int DB, int StartByteAdr, VarType VarType, int VarCount)
public object Read(DataType DataType, int DB, int StartByteAdr, VarType VarType, int VarCount)
{
byte[] bytes = null;
int cntBytes = 0;
switch (VarType)
{
case VarType.Byte:
cntBytes = VarCount;
if (cntBytes < 1) cntBytes = 1;
bytes = ReadBytes(DataType, DB, StartByteAdr, cntBytes);
if (bytes == null) return null;
if (VarCount == 1)
return bytes[0];
else
return bytes;
case VarType.Word:
cntBytes = VarCount * 2;
bytes = ReadBytes(DataType, DB, StartByteAdr, cntBytes);
if (bytes == null) return null;
if (VarCount == 1)
return Types.Word.FromByteArray(bytes);
else
return Types.Word.ToArray(bytes);
case VarType.Int:
cntBytes = VarCount * 2;
bytes = ReadBytes(DataType, DB, StartByteAdr, cntBytes);
if (bytes == null) return null;
if (VarCount == 1)
return Types.Int.FromByteArray(bytes);
else
return Types.Int.ToArray(bytes);
case VarType.DWord:
cntBytes = VarCount * 4;
bytes = ReadBytes(DataType, DB, StartByteAdr, cntBytes);
if (bytes == null) return null;
if (VarCount == 1)
return Types.DWord.FromByteArray(bytes);
else
return Types.DWord.ToArray(bytes);
case VarType.DInt:
cntBytes = VarCount * 4;
bytes = ReadBytes(DataType, DB, StartByteAdr, cntBytes);
if (bytes == null) return null;
if (VarCount == 1)
return Types.DInt.FromByteArray(bytes);
else
return Types.DInt.ToArray(bytes);
case VarType.Real:
cntBytes = VarCount * 4;
bytes = ReadBytes(DataType, DB, StartByteAdr, cntBytes);
if (bytes == null) return null;
if (VarCount == 1)
return Types.Double.FromByteArray(bytes);
else
return Types.Double.ToArray(bytes);
case VarType.String:
cntBytes = VarCount;
bytes = ReadBytes(DataType, DB, StartByteAdr, cntBytes);
if (bytes == null) return null;
return Types.String.FromByteArray(bytes);
case VarType.Timer:
cntBytes = VarCount * 2;
bytes = ReadBytes(DataType, DB, StartByteAdr, cntBytes);
if (bytes == null) return null;
if (VarCount == 1)
return Types.Timer.FromByteArray(bytes);
else
return Types.Timer.ToArray(bytes);
case VarType.Counter:
cntBytes = VarCount * 2;
bytes = ReadBytes(DataType, DB, StartByteAdr, cntBytes);
if (bytes == null) return null;
if (VarCount == 1)
return Types.Counter.FromByteArray(bytes);
else
return Types.Counter.ToArray(bytes);
default:
return null;
}
return null;
}
#endregion
#region Read(string variable)
public object Read(string variable)
{
DataType mDataType;
int mDB;
int mByte;
int mBit;
byte objByte;
UInt16 objUInt16;
UInt32 objUInt32;
double objDouble;
bool[] objBoolArray;
string txt = variable.ToUpper();
txt = txt.Replace(" ", ""); // remove spaces
try
{
switch (txt.Substring(0, 2))
{
case "DB":
string[] strings = txt.Split(new char[] { '.' });
if (strings.Length < 2)
throw new Exception();
mDB = int.Parse(strings[0].Substring(2));
mDataType = DataType.DataBlock;
string dbType = strings[1].Substring(0, 3);
int dbIndex = int.Parse(strings[1].Substring(3));
switch (dbType)
{
case "DBB":
byte obj = (byte)Read(DataType.DataBlock, mDB, dbIndex, VarType.Byte, 1);
return obj;
case "DBW":
UInt16 objI = (UInt16)Read(DataType.DataBlock, mDB, dbIndex, VarType.Word, 1);
return objI;
case "DBD":
UInt32 objU = (UInt32)Read(DataType.DataBlock, mDB, dbIndex, VarType.DWord, 1);
return objU;
case "DBX":
mByte = dbIndex;
mBit = int.Parse(strings[2]);
if (mBit > 7) throw new Exception();
objBoolArray = (bool[])Read(DataType.DataBlock, mDB, mByte, VarType.Bit, 1);
return objBoolArray[mBit];
default:
throw new Exception();
}
case "EB":
// Eingangsbyte
objByte = (byte)Read(DataType.Input, 0, int.Parse(txt.Substring(2)), VarType.Byte, 1);
return objByte;
case "EW":
// Eingangswort
objUInt16 = (UInt16)Read(DataType.Input, 0, int.Parse(txt.Substring(2)), VarType.Word, 1);
return objUInt16;
case "ED":
// Eingangsdoppelwort
objUInt32 = (UInt32)Read(DataType.Input, 0, int.Parse(txt.Substring(2)), VarType.DWord, 1);
return objUInt32;
case "AB":
// Ausgangsbyte
objByte = (byte)Read(DataType.Output, 0, int.Parse(txt.Substring(2)), VarType.Byte, 1);
return objByte;
case "AW":
// Ausgangswort
objUInt16 = (UInt16)Read(DataType.Output, 0, int.Parse(txt.Substring(2)), VarType.Word, 1);
return objUInt16;
case "AD":
// Ausgangsdoppelwort
objUInt32 = (UInt32)Read(DataType.Output, 0, int.Parse(txt.Substring(2)), VarType.DWord, 1);
return objUInt32;
case "MB":
// Merkerbyte
objByte = (byte)Read(DataType.Marker, 0, int.Parse(txt.Substring(2)), VarType.Byte, 1);
return objByte;
case "MW":
// Merkerwort
objUInt16 = (UInt16)Read(DataType.Marker, 0, int.Parse(txt.Substring(2)), VarType.Word, 1);
return objUInt16;
case "MD":
// Merkerdoppelwort
objUInt32 = (UInt32)Read(DataType.Marker, 0, int.Parse(txt.Substring(2)), VarType.DWord, 1);
return objUInt32;
default:
switch (txt.Substring(0, 1))
{
case "E":
case "I":
// Eingang
mDataType = DataType.Input;
break;
case "A":
case "O":
// Ausgang
mDataType = DataType.Output;
break;
case "M":
// Merker
mDataType = DataType.Marker;
break;
case "T":
// Timer
objDouble = (double)Read(DataType.Timer, 0, int.Parse(txt.Substring(1)), VarType.Timer, 1);
return objDouble;
case "Z":
case "C":
// Counter
objUInt16 = (UInt16)Read(DataType.Counter, 0, int.Parse(txt.Substring(1)), VarType.Counter, 1);
return objUInt16;
default:
throw new Exception();
}
string txt2 = txt.Substring(1);
if (txt2.IndexOf(".") == -1) throw new Exception();
mByte = int.Parse(txt2.Substring(0, txt2.IndexOf(".")));
mBit = int.Parse(txt2.Substring(txt2.IndexOf(".") + 1));
if (mBit > 7) throw new Exception();
objBoolArray = (bool[])Read(mDataType, 0, mByte, VarType.Bit, 1);
return objBoolArray[mBit];
}
}
catch
{
lastErrorCode = ErrorCode.WrongVarFormat;
lastErrorString = "Die Variable '" + variable + "' konnte nicht entschlüsselt werden!";
return lastErrorCode;
}
}
#endregion
#region ReadStruct(Type structType, int DB)
public object ReadStruct(Type structType, int DB)
{
double numBytes = Types.Struct.GetStructSize(structType);
// now read the package
byte[] bytes = (byte[])Read(DataType.DataBlock, DB, 0, VarType.Byte, (int)numBytes);
// and decode it
return Types.Struct.FromBytes(structType, bytes);
}
#endregion
#region WriteBytes(DataType DataType, int DB, int StartByteAdr, byte[] value)
public ErrorCode WriteBytes(DataType DataType, int DB, int StartByteAdr, byte[] value)
{
byte[] bReceive = new byte[513];
int varCount = 0;
try
{
varCount = value.Length;
// first create the header
int packageSize = 35 + value.Length;
Types.ByteArray package = new Types.ByteArray(packageSize);
package.Add(new byte[] { 3, 0, 0 });
package.Add((byte)packageSize);
package.Add(new byte[] { 2, 0xf0, 0x80, 0x32, 1, 0, 0 });
package.Add(Types.Word.ToByteArray((ushort)(varCount - 1)));
package.Add(new byte[] { 0, 0x0e });
package.Add(Types.Word.ToByteArray((ushort)(varCount + 4)));
package.Add(new byte[] { 0x05, 0x01, 0x12, 0x0a, 0x10, 0x02 });
package.Add(Types.Word.ToByteArray((ushort)varCount));
package.Add(Types.Word.ToByteArray((ushort)(DB)));
package.Add((byte)DataType);
package.Add((byte)0);
package.Add(Types.Word.ToByteArray((ushort)(StartByteAdr * 8)));
package.Add(new byte[] { 0, 4 });
package.Add(Types.Word.ToByteArray((ushort)(varCount * 8)));
// now join the header and the data
package.Add(value);
mSocket.Send(package.array, package.array.Length, SocketFlags.None);
int numReceived = mSocket.Receive(bReceive, 512, SocketFlags.None);
if (bReceive[21] != 0xff) throw new Exception(ErrorCode.WrongNumberReceivedBytes.ToString());
return ErrorCode.NoError;
}
catch
{
lastErrorCode = ErrorCode.WriteData;
lastErrorString = "";
return lastErrorCode;
}
}
#endregion
#region Write(DataType DataType, int DB, int StartByteAdr, object value)
public object Write(DataType DataType, int DB, int StartByteAdr, object value)
{
byte[] package = null;
switch (value.GetType().Name)
{
case "Byte":
package = Types.Byte.ToByteArray((byte)value);
break;
case "Int16":
package = Types.Int.ToByteArray((Int16)value);
break;
case "UInt16":
package = Types.Word.ToByteArray((UInt16)value);
break;
case "Int32":
package = Types.DInt.ToByteArray((Int32)value);
break;
case "UInt32":
package = Types.DWord.ToByteArray((UInt32)value);
break;
case "Double":
package = Types.Double.ToByteArray((Double)value);
break;
case "Byte[]":
package = (byte[])value;
break;
case "Int16[]":
package = Types.Int.ToByteArray((Int16[])value);
break;
case "UInt16[]":
package = Types.Word.ToByteArray((UInt16[])value);
break;
case "Int32[]":
package = Types.DInt.ToByteArray((Int32[])value);
break;
case "UInt32[]":
package = Types.DWord.ToByteArray((UInt32[])value);
break;
case "Double[]":
package = Types.Double.ToByteArray((double[])value);
break;
case "String":
package = Types.String.ToByteArray(value as string);
break;
default:
return ErrorCode.WrongVarFormat;
}
return WriteBytes(DataType, DB, StartByteAdr, package);
}
#endregion
#region Write(string variable, object value)
public object Write(string variable, object value)
{
DataType mDataType;
int mDB;
int mByte;
int mBit;
string txt2;
byte _byte;
object objValue;
string txt = variable.ToUpper();
txt = txt.Replace(" ", ""); // Leerzeichen entfernen
try
{
switch (txt.Substring(0, 2))
{
case "DB":
string[] strings = txt.Split(new char[]{'.'});
if (strings.Length < 2)
throw new Exception();
mDB = int.Parse(strings[0].Substring(2));
mDataType = DataType.DataBlock;
string dbType = strings[1].Substring(0, 3);
int dbIndex = int.Parse(strings[1].Substring(3));
switch (dbType)
{
case "DBB":
objValue = Convert.ChangeType(value, typeof(byte));
return Write(DataType.DataBlock, mDB, dbIndex, (byte)objValue);
case "DBW":
objValue = Convert.ChangeType(value, typeof(UInt16));
return Write(DataType.DataBlock, mDB, dbIndex, (UInt16)objValue);
case "DBD":
objValue = Convert.ChangeType(value, typeof(UInt32));
return Write(DataType.DataBlock, mDB, dbIndex, (UInt32)objValue);
case "DBX":
mByte = dbIndex;
mBit = int.Parse(strings[2]);
if (mBit > 7) throw new Exception();
byte b = (byte)Read(DataType.DataBlock, mDB, mByte, VarType.Byte, 1);
if ((int)value == 1)
b = (byte)(b | (byte)Math.Pow(2, mBit)); // Bit setzen
else
b = (byte)(b & (b ^ (byte)Math.Pow(2, mBit))); // Bit rücksetzen
return Write(DataType.DataBlock, mDB, mByte, (byte)b);
case "DBS":
// DB-String
return Write(DataType.DataBlock, mDB, dbIndex, (string)value);
default:
throw new Exception();
}
case "EB":
// Eingangsbyte
objValue = Convert.ChangeType(value, typeof(byte));
return Write(DataType.Input, 0, int.Parse(txt.Substring(2)), (byte)objValue);
case "EW":
// Eingangswort
objValue = Convert.ChangeType(value, typeof(UInt16));
return Write(DataType.Input, 0, int.Parse(txt.Substring(2)), (UInt16)objValue);
case "ED":
// Eingangsdoppelwort
objValue = Convert.ChangeType(value, typeof(UInt32));
return Write(DataType.Input, 0, int.Parse(txt.Substring(2)), (UInt32)objValue);
case "AB":
// Ausgangsbyte
objValue = Convert.ChangeType(value, typeof(byte));
return Write(DataType.Output, 0, int.Parse(txt.Substring(2)), (byte)objValue);
case "AW":
// Ausgangswort
objValue = Convert.ChangeType(value, typeof(UInt16));
return Write(DataType.Output, 0, int.Parse(txt.Substring(2)), (UInt16)objValue);
case "AD":
// Ausgangsdoppelwort
objValue = Convert.ChangeType(value, typeof(UInt32));
return Write(DataType.Output, 0, int.Parse(txt.Substring(2)), (UInt32)objValue);
case "MB":
// Merkerbyte
objValue = Convert.ChangeType(value, typeof(byte));
return Write(DataType.Marker, 0, int.Parse(txt.Substring(2)), (byte)objValue);
case "MW":
// Merkerwort
objValue = Convert.ChangeType(value, typeof(UInt16));
return Write(DataType.Marker, 0, int.Parse(txt.Substring(2)), (UInt16)objValue);
case "MD":
// Merkerdoppelwort
return Write(DataType.Marker, 0, int.Parse(txt.Substring(2)), value);
default:
switch (txt.Substring(0, 1))
{
case "E":
case "I":
// Eingang
mDataType = DataType.Input;
break;
case "A":
case "O":
// Ausgang
mDataType = DataType.Output;
break;
case "M":
// Merker
mDataType = DataType.Marker;
break;
case "T":
// Timer
return Write(DataType.Timer, 0, int.Parse(txt.Substring(1)), (double)value);
case "Z":
case "C":
// Zähler
return Write(DataType.Counter, 0, int.Parse(txt.Substring(1)), (short)value);
default:
throw new Exception("Unbekannte Variable");
}
txt2 = txt.Substring(1);
if (txt2.IndexOf(".") == -1) throw new Exception("Unbekannte Variable");
mByte = int.Parse(txt2.Substring(0, txt2.IndexOf(".")));
mBit = int.Parse(txt2.Substring(txt2.IndexOf(".") + 1));
if (mBit > 7) throw new Exception("Unbekannte Variable");
_byte = (byte)Read(mDataType, 0, mByte, VarType.Byte, 1);
if ((int)value == 1)
_byte = (byte)(_byte | (byte)Math.Pow(2, mBit)); // Bit setzen
else
_byte = (byte)(_byte & (_byte ^ (byte)Math.Pow(2, mBit))); // Bit rücksetzen
return Write(mDataType, 0, mByte, (byte)_byte);
}
}
catch (Exception ex)
{
string msg = ex.Message;
lastErrorCode = ErrorCode.WrongVarFormat;
lastErrorString = "Die Variable '" + variable + "' konnte nicht entschlüsselt werden!";
return lastErrorCode;
}
}
#endregion
#region WriteStruct(object value, int DB)
public ErrorCode WriteStruct(object structValue, int DB)
{
try
{
byte[] bytes = Types.Struct.ToBytes(structValue);
ErrorCode errCode = WriteBytes(DataType.DataBlock, DB, 0, bytes);
return errCode;
}
catch
{
lastErrorCode = ErrorCode.WriteData;
lastErrorString = "Fehler beim Schreiben der Daten aufgetreten!";
return lastErrorCode;
}
}
#endregion
public void Dispose()
{
if (mSocket != null)
{
((IDisposable)mSocket).Dispose();
}
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die mit einer Assembly verknüpft sind.
[assembly: AssemblyTitle("S7.Net")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("S7.Net")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("1c01e753-a660-4c35-a681-c6f6a7deee83")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

106
S7.Net/S7.Net.csproj Normal file
View File

@@ -0,0 +1,106 @@
<?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>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BFD484F9-3F04-42A2-BF2A-60A189A25DCF}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>S7.Net</RootNamespace>
<AssemblyName>S7.Net</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</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>
</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>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Conversion.cs" />
<Compile Include="Enums.cs" />
<Compile Include="Interfaces\IPLC.cs" />
<Compile Include="PLC.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Types\Boolean.cs" />
<Compile Include="Types\Byte.cs" />
<Compile Include="Types\ByteArray.cs" />
<Compile Include="Types\Double.cs" />
<Compile Include="Types\DWord.cs" />
<Compile Include="Types\Int.cs" />
<Compile Include="Types\DInt.cs" />
<Compile Include="Types\Counter.cs" />
<Compile Include="Types\Timer.cs" />
<Compile Include="Types\String.cs" />
<Compile Include="Types\Word.cs" />
<Compile Include="Types\Struct.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</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>

28
S7.Net/Types/Boolean.cs Normal file
View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class Boolean
{
public static bool GetValue(byte value, int bit)
{
if ((value & (int)Math.Pow(2, bit)) != 0)
return true;
else
return false;
}
public static byte SetBit(byte value, int bit)
{
return (byte)(value | (byte)Math.Pow(2, bit));
}
public static byte ClearBit(byte value, int bit)
{
return (byte)(value & (byte)(~(byte)Math.Pow(2, bit)));
}
}
}

24
S7.Net/Types/Byte.cs Normal file
View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class Byte
{
// publics
#region ToByteArray
public static byte[] ToByteArray(byte value)
{
byte[] bytes = new byte[] { value};
return bytes;
}
#endregion
#region FromByteArray
public static byte FromByteArray(byte[] bytes)
{
return bytes[0];
}
#endregion
}
}

42
S7.Net/Types/ByteArray.cs Normal file
View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace S7.Types
{
class ByteArray
{
List<byte> list = new List<byte>();
public byte[] array
{
get { return list.ToArray(); }
}
public ByteArray()
{
list = new List<byte>();
}
public ByteArray(int size)
{
list = new List<byte>(size);
}
public void Clear()
{
list = new List<byte>();
}
public void Add(byte item)
{
list.Add(item);
}
public void Add(byte[] items)
{
list.AddRange(items);
}
}
}

63
S7.Net/Types/Counter.cs Normal file
View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class Counter
{
// publics
#region FromByteArray
public static UInt16 FromByteArray(byte[] bytes)
{
// bytes[0] -> HighByte
// bytes[1] -> LowByte
return FromBytes(bytes[1], bytes[0]);
}
#endregion
#region FromBytes
public static UInt16 FromBytes(byte LoVal, byte HiVal)
{
return (UInt16)(HiVal * 256 + LoVal);
}
#endregion
#region ToByteArray
public static byte[] ToByteArray(UInt16 value)
{
byte[] bytes = new byte[2];
int x = 2;
long valLong = (long)((UInt16)value);
for (int cnt = 0; cnt < x; cnt++)
{
Int64 x1 = (Int64)Math.Pow(256, (cnt));
Int64 x3 = (Int64)(valLong / x1);
bytes[x - cnt - 1] = (byte)(x3 & 255);
valLong -= bytes[x - cnt - 1] * x1;
}
return bytes;
}
public static byte[] ToByteArray(UInt16[] value)
{
ByteArray arr = new ByteArray();
foreach (UInt16 val in value)
arr.Add(ToByteArray(val));
return arr.array;
}
#endregion
#region ToArray
public static UInt16[] ToArray(byte[] bytes)
{
UInt16[] values = new UInt16[bytes.Length / 2];
int counter = 0;
for (int cnt = 0; cnt < bytes.Length / 2; cnt++)
values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++] });
return values;
}
#endregion
}
}

73
S7.Net/Types/DInt.cs Normal file
View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class DInt
{
// publics
#region FromByteArray
public static Int32 FromByteArray(byte[] bytes)
{
return FromBytes(bytes[3], bytes[2], bytes[1], bytes[0]);
}
#endregion
#region FromBytes
public static Int32 FromBytes(byte v1, byte v2, byte v3, byte v4)
{
return (Int32)(v1 + v2 * Math.Pow(2, 8) + v3 * Math.Pow(2, 16) + v4 * Math.Pow(2, 24));
}
#endregion
#region ToByteArray
public static byte[] ToByteArray(Int32 value)
{
byte[] bytes = new byte[4];
int x = 4;
long valLong = (long)((Int32)value);
for (int cnt = 0; cnt < x; cnt++)
{
Int64 x1 = (Int64)Math.Pow(256, (cnt));
Int64 x3 = (Int64)(valLong / x1);
bytes[x - cnt - 1] = (byte)(x3 & 255);
valLong -= bytes[x - cnt - 1] * x1;
}
return bytes;
}
public static byte[] ToByteArray(Int32[] value)
{
ByteArray arr = new ByteArray();
foreach (Int32 val in value)
arr.Add(ToByteArray(val));
return arr.array;
}
#endregion
#region ToArray
public static Int32[] ToArray(byte[] bytes)
{
Int32[] values = new Int32[bytes.Length / 4];
int counter = 0;
for (int cnt = 0; cnt < bytes.Length / 4; cnt++)
values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++], bytes[counter++], bytes[counter++] });
return values;
}
#endregion
// conversion
public static Int32 CDWord(Int64 value)
{
if (value > Int32.MaxValue)
{
value -= (long)Int32.MaxValue + 1;
value = (long)Int32.MaxValue + 1 - value;
value *= -1;
}
return (int)value;
}
}
}

61
S7.Net/Types/DWord.cs Normal file
View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class DWord
{
// publics
#region FromByteArray
public static UInt32 FromByteArray(byte[] bytes)
{
return FromBytes(bytes[3], bytes[2], bytes[1], bytes[0]);
}
#endregion
#region FromBytes
public static UInt32 FromBytes(byte v1, byte v2, byte v3, byte v4)
{
return (UInt32)(v1 + v2 * Math.Pow(2, 8) + v3 * Math.Pow(2, 16) + v4 * Math.Pow(2, 24));
}
#endregion
#region ToByteArray
public static byte[] ToByteArray(UInt32 value)
{
byte[] bytes = new byte[4];
int x = 4;
long valLong = (long)((UInt32)value);
for (int cnt = 0; cnt < x; cnt++)
{
Int64 x1 = (Int64)Math.Pow(256, (cnt));
Int64 x3 = (Int64)(valLong / x1);
bytes[x - cnt - 1] = (byte)(x3 & 255);
valLong -= bytes[x - cnt - 1] * x1;
}
return bytes;
}
public static byte[] ToByteArray(UInt32[] value)
{
ByteArray arr = new ByteArray();
foreach (UInt32 val in value)
arr.Add(ToByteArray(val));
return arr.array;
}
#endregion
#region ToArray
public static UInt32[] ToArray(byte[] bytes)
{
UInt32[] values = new UInt32[bytes.Length / 4];
int counter = 0;
for (int cnt = 0; cnt < bytes.Length / 4; cnt++)
values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++], bytes[counter++], bytes[counter++] });
return values;
}
#endregion
}
}

169
S7.Net/Types/Double.cs Normal file
View File

@@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Text;
using S7;
namespace S7.Types
{
public static class Double
{
// publics
#region FromByteArray
public static double FromByteArray(byte[] bytes)
{
byte v1 = bytes[0];
byte v2 = bytes[1];
byte v3 = bytes[2];
byte v4 = bytes[3];
if ((int)v1 + v2 + v3 + v4 == 0)
{
return 0.0;
}
else
{
// nun String bilden
string txt = ValToBinString(v1) + ValToBinString(v2) + ValToBinString(v3) + ValToBinString(v4);
// erstmal das Vorzeichen
int vz = int.Parse(txt.Substring(0, 1));
int exd = Conversion.BinStringToInt32(txt.Substring(1, 8));
string ma = txt.Substring(9, 23);
double mantisse = 1;
double faktor = 1.0;
//das ist die Anzahl der restlichen bit's
for (int cnt = 0; cnt <= 22; cnt++)
{
faktor = faktor / 2.0;
//entspricht 2^-y
if (ma.Substring(cnt, 1) == "1")
{
mantisse = mantisse + faktor;
}
}
return Math.Pow((-1), vz) * Math.Pow(2, (exd - 127)) * mantisse;
}
}
#endregion
#region FromDWord
public static double FromDWord(Int32 value)
{
byte[] b = S7.Types.DInt.ToByteArray(value);
double d = FromByteArray(b);
return d;
}
public static double FromDWord(UInt32 value)
{
byte[] b = S7.Types.DWord.ToByteArray(value);
double d = FromByteArray(b);
return d;
}
#endregion
#region ToByteArray
public static byte[] ToByteArray(double value)
{
double wert = (double)value;
string binString = "";
byte[] bytes = new byte[4];
if (wert != 0f)
{
if (wert < 0)
{
wert *= -1;
binString = "1";
}
else
{
binString = "0";
}
int exponent = (int)Math.Floor((double)Math.Log(wert) / Math.Log(2.0));
wert = wert / (Math.Pow(2, exponent)) - 1;
binString += ValToBinString((byte)(exponent + 127));
for (int cnt = 1; cnt <= 23; cnt++)
{
if (!(wert - System.Math.Pow(2, -cnt) < 0))
{
wert = wert - System.Math.Pow(2, -cnt);
binString += "1";
}
else
binString += "0";
}
bytes[0] = (byte)BinStringToByte(binString.Substring(0, 8));
bytes[1] = (byte)BinStringToByte(binString.Substring(8, 8));
bytes[2] = (byte)BinStringToByte(binString.Substring(16, 8));
bytes[3] = (byte)BinStringToByte(binString.Substring(24, 8));
}
else
{
bytes[0] = 0;
bytes[1] = 0;
bytes[2] = 0;
bytes[3] = 0;
}
return bytes;
}
public static byte[] ToByteArray(double[] value)
{
ByteArray arr = new ByteArray();
foreach (double val in value)
arr.Add(ToByteArray(val));
return arr.array;
}
#endregion
#region ToArray
public static double[] ToArray(byte[] bytes)
{
double[] values = new double[bytes.Length / 4];
int counter = 0;
for (int cnt = 0; cnt < bytes.Length / 4; cnt++)
values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++], bytes[counter++], bytes[counter++] });
return values;
}
#endregion
// privates
#region ValToBinString
private static string ValToBinString(byte value)
{
string txt = "";
for (int cnt = 7; cnt >= 0; cnt += -1)
{
if ((value & (byte)Math.Pow(2, cnt)) > 0)
txt += "1";
else
txt += "0";
}
return txt;
}
#endregion
#region BinStringToByte
private static byte? BinStringToByte(string txt)
{
int cnt = 0;
int ret = 0;
if (txt.Length == 8)
{
for (cnt = 7; cnt >= 0; cnt += -1)
{
if (int.Parse(txt.Substring(cnt, 1)) == 1)
{
ret += (int)(Math.Pow(2, (txt.Length - 1 - cnt)));
}
}
return (byte)ret;
}
return null;
}
#endregion
}
}

76
S7.Net/Types/Int.cs Normal file
View File

@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class Int
{
// publics
#region FromByteArray
public static Int16 FromByteArray(byte[] bytes)
{
// bytes[0] -> HighByte
// bytes[1] -> LowByte
return FromBytes(bytes[1], bytes[0]);
}
#endregion
#region FromBytes
public static Int16 FromBytes(byte LoVal, byte HiVal)
{
return (Int16)(HiVal * 256 + LoVal);
}
#endregion
#region ToByteArray
public static byte[] ToByteArray(Int16 value)
{
byte[] bytes = new byte[2];
int x = 2;
long valLong = (long)((Int16)value);
for (int cnt = 0; cnt < x; cnt++)
{
Int64 x1 = (Int64)Math.Pow(256, (cnt));
Int64 x3 = (Int64)(valLong / x1);
bytes[x - cnt - 1] = (byte)(x3 & 255);
valLong -= bytes[x - cnt - 1] * x1;
}
return bytes;
}
public static byte[] ToByteArray(Int16[] value)
{
ByteArray arr = new ByteArray();
foreach (Int16 val in value)
arr.Add(ToByteArray(val));
return arr.array;
}
#endregion
#region ToArray
public static Int16[] ToArray(byte[] bytes)
{
Int16[] values = new Int16[bytes.Length / 2];
int counter = 0;
for (int cnt = 0; cnt < bytes.Length / 2; cnt++)
values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++] });
return values;
}
#endregion
// conversion
public static Int16 CWord(int value)
{
if (value > 32767)
{
value -= 32768;
value = 32768 - value;
value *= -1;
}
return (short)value;
}
}
}

38
S7.Net/Types/String.cs Normal file
View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class String
{
// publics
#region ToByteArray
public static byte[] ToByteArray(string value)
{
string txt = (string)value;
char[] ca = txt.ToCharArray();
byte[] bytes = new byte[txt.Length];
for (int cnt = 0; cnt <= ca.Length - 1; cnt++)
bytes[cnt] = (byte)Asc(ca[cnt].ToString());
return bytes;
}
#endregion
#region FromByteArray
public static string FromByteArray(byte[] bytes)
{
return System.Text.Encoding.ASCII.GetString(bytes);
}
#endregion
// privates
private static int Asc(string s)
{
byte[] b = System.Text.Encoding.ASCII.GetBytes(s);
if (b.Length > 0)
return b[0];
return 0;
}
}
}

204
S7.Net/Types/Struct.cs Normal file
View File

@@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class Struct
{
/// <summary>
/// Gets the size of the struct in bytes.
/// </summary>
/// <param name="structType">the type of the struct</param>
/// <returns>the number of bytes</returns>
public static int GetStructSize(Type structType)
{
double numBytes = 0.0;
System.Reflection.FieldInfo[] infos = structType.GetFields();
foreach (System.Reflection.FieldInfo info in infos)
{
switch (info.FieldType.Name)
{
case "Boolean":
numBytes += 0.125;
break;
case "Byte":
numBytes = Math.Ceiling(numBytes);
numBytes++;
break;
case "Int16":
case "UInt16":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
numBytes += 2;
break;
case "Int32":
case "UInt32":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
numBytes += 4;
break;
case "Float":
case "Double":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
numBytes += 4;
break;
}
}
return (int)numBytes;
}
/// <summary>
/// Creates a struct of a specified type by an array of bytes.
/// </summary>
/// <param name="structType">The struct type</param>
/// <param name="bytes">The array of bytes</param>
/// <returns>The object depending on the struct type or null if fails(array-length != struct-length</returns>
public static object FromBytes(Type structType, byte[] bytes)
{
if (bytes == null)
return null;
if (bytes.Length != GetStructSize(structType))
return null;
// and decode it
int bytePos = 0;
int bitPos = 0;
double numBytes = 0.0;
object structValue = Activator.CreateInstance(structType);
System.Reflection.FieldInfo[] infos = structValue.GetType().GetFields();
foreach (System.Reflection.FieldInfo info in infos)
{
switch (info.FieldType.Name)
{
case "Boolean":
// get the value
bytePos = (int)Math.Floor(numBytes);
bitPos = (int)((numBytes - (double)bytePos) / 0.125);
if ((bytes[bytePos] & (int)Math.Pow(2, bitPos)) != 0)
info.SetValue(structValue, true);
else
info.SetValue(structValue, false);
numBytes += 0.125;
break;
case "Byte":
numBytes = Math.Ceiling(numBytes);
info.SetValue(structValue, (byte)(bytes[(int)numBytes]));
numBytes++;
break;
case "Int16":
case "UInt16":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
// hier auswerten
info.SetValue(structValue, S7.Types.Word.FromBytes(bytes[(int)numBytes + 1],
bytes[(int)numBytes]));
numBytes += 2;
break;
case "Int32":
case "UInt32":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
// hier auswerten
info.SetValue(structValue, S7.Types.DWord.FromBytes(bytes[(int)numBytes],
bytes[(int)numBytes + 1],
bytes[(int)numBytes + 2],
bytes[(int)numBytes + 3]));
numBytes += 4;
break;
case "Double":
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
// hier auswerten
info.SetValue(structValue, S7.Types.Double.FromByteArray(new byte[] { bytes[(int)numBytes],
bytes[(int)numBytes + 1],
bytes[(int)numBytes + 2],
bytes[(int)numBytes + 3] }));
numBytes += 4;
break;
}
}
return structValue;
}
/// <summary>
/// Creates a byte array depending on the struct type.
/// </summary>
/// <param name="structValue">The struct object</param>
/// <returns>A byte array or null if fails.</returns>
public static byte[] ToBytes(object structValue)
{
Type type = structValue.GetType();
int size = S7.Types.Struct.GetStructSize(type);
byte[] bytes = new byte[size];
byte[] bytes2 = null;
int bytePos = 0;
int bitPos = 0;
double numBytes = 0.0;
System.Reflection.FieldInfo[] infos = type.GetFields();
foreach (System.Reflection.FieldInfo info in infos)
{
bytes2 = null;
switch (info.FieldType.Name)
{
case "Boolean":
// get the value
bytePos = (int)Math.Floor(numBytes);
bitPos = (int)((numBytes - (double)bytePos) / 0.125);
if ((bool)info.GetValue(structValue))
bytes[bytePos] |= (byte)Math.Pow(2, bitPos); // is true
else
bytes[bytePos] &= (byte)(~(byte)Math.Pow(2, bitPos)); // is false
numBytes += 0.125;
break;
case "Byte":
numBytes = (int)Math.Ceiling(numBytes);
bytePos = (int)numBytes;
bytes[bytePos] = (byte)info.GetValue(structValue);
numBytes++;
break;
case "Int16":
bytes2 = S7.Types.Int.ToByteArray((Int16)info.GetValue(structValue));
break;
case "UInt16":
bytes2 = S7.Types.Word.ToByteArray((UInt16)info.GetValue(structValue));
break;
case "Int32":
bytes2 = S7.Types.DInt.ToByteArray((Int32)info.GetValue(structValue));
break;
case "UInt32":
bytes2 = S7.Types.DWord.ToByteArray((UInt32)info.GetValue(structValue));
break;
case "Double":
bytes2 = S7.Types.Double.ToByteArray((double)info.GetValue(structValue));
break;
}
if (bytes2 != null)
{
// add them
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
bytePos = (int)numBytes;
for (int bCnt=0; bCnt<bytes2.Length; bCnt++)
bytes[bytePos + bCnt] = bytes2[bCnt];
numBytes += bytes2.Length;
}
}
return bytes;
}
}
}

76
S7.Net/Types/Timer.cs Normal file
View File

@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class Timer
{
// publics
#region FromByteArray
public static double FromByteArray(byte[] bytes)
{
double wert = 0;
Int16 value = (Int16)Types.Word.FromBytes(bytes[1], bytes[0]);
string txt = Conversion.ValToBinString(value);
wert = Conversion.BinStringToInt32(txt.Substring(4, 4)) * 100.0;
wert += Conversion.BinStringToInt32(txt.Substring(8, 4)) * 10.0;
wert += Conversion.BinStringToInt32(txt.Substring(12, 4));
switch (txt.Substring(2, 2))
{
case "00":
wert *= 0.01;
break;
case "01":
wert *= 0.1;
break;
case "10":
wert *= 1.0;
break;
case "11":
wert *= 10.0;
break;
}
return wert;
}
#endregion
#region ToByteArray
public static byte[] ToByteArray(UInt16 value)
{
byte[] bytes = new byte[2];
int x = 2;
long valLong = (long)((UInt16)value);
for (int cnt = 0; cnt < x; cnt++)
{
Int64 x1 = (Int64)Math.Pow(256, (cnt));
Int64 x3 = (Int64)(valLong / x1);
bytes[x - cnt - 1] = (byte)(x3 & 255);
valLong -= bytes[x - cnt - 1] * x1;
}
return bytes;
}
public static byte[] ToByteArray(UInt16[] value)
{
ByteArray arr = new ByteArray();
foreach (UInt16 val in value)
arr.Add(ToByteArray(val));
return arr.array;
}
#endregion
#region ToArray
public static double[] ToArray(byte[] bytes)
{
double[] values = new double[bytes.Length / 2];
int counter = 0;
for (int cnt = 0; cnt < bytes.Length / 2; cnt++)
values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++] });
return values;
}
#endregion
}
}

63
S7.Net/Types/Word.cs Normal file
View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace S7.Types
{
public static class Word
{
// publics
#region FromByteArray
public static UInt16 FromByteArray(byte[] bytes)
{
// bytes[0] -> HighByte
// bytes[1] -> LowByte
return FromBytes(bytes[1], bytes[0]);
}
#endregion
#region FromBytes
public static UInt16 FromBytes(byte LoVal, byte HiVal)
{
return (UInt16)(HiVal * 256 + LoVal);
}
#endregion
#region ToByteArray
public static byte[] ToByteArray(UInt16 value)
{
byte[] bytes = new byte[2];
int x = 2;
long valLong = (long)((UInt16)value);
for (int cnt = 0; cnt < x; cnt++)
{
Int64 x1 = (Int64)Math.Pow(256, (cnt));
Int64 x3 = (Int64)(valLong / x1);
bytes[x - cnt - 1] = (byte)(x3 & 255);
valLong -= bytes[x - cnt - 1] * x1;
}
return bytes;
}
public static byte[] ToByteArray(UInt16[] value)
{
ByteArray arr = new ByteArray();
foreach (UInt16 val in value)
arr.Add(ToByteArray(val));
return arr.array;
}
#endregion
#region ToArray
public static UInt16[] ToArray(byte[] bytes)
{
UInt16[] values = new UInt16[bytes.Length / 2];
int counter = 0;
for (int cnt = 0; cnt < bytes.Length / 2; cnt++)
values[cnt] = FromByteArray(new byte[] { bytes[counter++], bytes[counter++] });
return values;
}
#endregion
}
}

26
S7.sln Normal file
View File

@@ -0,0 +1,26 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S7.Net", "S7.Net\S7.Net.csproj", "{BFD484F9-3F04-42A2-BF2A-60A189A25DCF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S7.Net.Test", "S7.Net.Test\S7.Net.Test.csproj", "{D34F7AF6-19DA-4AE6-9BB0-6666970F6838}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BFD484F9-3F04-42A2-BF2A-60A189A25DCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFD484F9-3F04-42A2-BF2A-60A189A25DCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFD484F9-3F04-42A2-BF2A-60A189A25DCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFD484F9-3F04-42A2-BF2A-60A189A25DCF}.Release|Any CPU.Build.0 = Release|Any CPU
{D34F7AF6-19DA-4AE6-9BB0-6666970F6838}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D34F7AF6-19DA-4AE6-9BB0-6666970F6838}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D34F7AF6-19DA-4AE6-9BB0-6666970F6838}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D34F7AF6-19DA-4AE6-9BB0-6666970F6838}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

BIN
packages/NUnit.2.6.2/NUnit.2.6.2.nupkg vendored Normal file

Binary file not shown.

30
packages/NUnit.2.6.2/NUnit.2.6.2.nuspec vendored Normal file
View File

@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>NUnit</id>
<version>2.6.2</version>
<title>NUnit</title>
<authors>Charlie Poole</authors>
<owners>Charlie Poole</owners>
<licenseUrl>http://nunit.org/nuget/license.html</licenseUrl>
<projectUrl>http://nunit.org/</projectUrl>
<iconUrl>http://nunit.org/nuget/nunit_32x32.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>NUnit features a fluent assert syntax, parameterized, generic and theory tests and is user-extensible. A number of runners, both from the NUnit project and by third parties, are able to execute NUnit tests.
Version 2.6 is the seventh major release of this well-known and well-tested programming tool.
This package includes only the framework assembly. You will need to install the NUnit.Runners package unless you are using a third-party runner.</description>
<summary>NUnit is a unit-testing framework for all .Net languages with a strong TDD focus.</summary>
<releaseNotes>Version 2.6 is the seventh major release of NUnit.
Unlike earlier versions, this package includes only the framework assembly. You will need to install the NUnit.Runners package unless you are using a third-party runner.
The nunit.mocks assembly is now provided by the NUnit.Mocks package. The pnunit.framework assembly is provided by the pNUnit package.</releaseNotes>
<language>en-US</language>
<tags>test testing tdd framework fluent assert theory plugin addin</tags>
<references>
<reference file="nunit.framework.dll" />
</references>
</metadata>
</package>

Binary file not shown.

File diff suppressed because it is too large Load Diff

15
packages/NUnit.2.6.2/license.txt vendored Normal file
View File

@@ -0,0 +1,15 @@
Copyright <20> 2002-2012 Charlie Poole
Copyright <20> 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov
Copyright <20> 2000-2002 Philip A. Craig
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required.
Portions Copyright <20> 2002-2012 Charlie Poole or Copyright <20> 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright <20> 2000-2002 Philip A. Craig
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

Binary file not shown.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Should</id>
<version>1.1.12.0</version>
<title>Should</title>
<authors>Eric Hexter</authors>
<owners>Eric Hexter</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>The Should Assertion Library provides a set of extension methods for test assertions for AAA and BDD style tests. It provides assertions only, and as a result it is Test runner agnostic. The assertions are a direct fork of the xUnit test assertions. This project was born because test runners Should be independent of the the assertions!</description>
<summary>The Should Assertion Library provides a set of extension methods for test assertions for AAA and BDD style tests. It provides assertions only, and as a result it is Test runner agnostic. The assertions are a direct fork of the xUnit test assertions. This project was born because test runners Should be independent of the the assertions!</summary>
<references>
<reference file="Should.dll" />
</references>
</metadata>
</package>

BIN
packages/Should.1.1.12.0/lib/Should.dll vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="..\S7.Net.Test\packages.config" />
</repositories>