diff --git a/S7.Net.UnitTest/Helpers/ConsoleManager.cs b/S7.Net.UnitTest/Helpers/ConsoleManager.cs
new file mode 100644
index 0000000..f110b92
--- /dev/null
+++ b/S7.Net.UnitTest/Helpers/ConsoleManager.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Security;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using System.IO;
+
+namespace S7.Net.UnitTest.Helpers
+{
+ [SuppressUnmanagedCodeSecurity]
+ public static class ConsoleManager
+ {
+ public static bool HasConsole
+ {
+ get { return NativeMethods.GetConsoleWindow() != IntPtr.Zero; }
+ }
+
+ ///
+ /// Creates a new console instance if the process is not attached to a console already.
+ ///
+ public static void Show()
+ {
+ //#if DEBUG
+ if (!HasConsole)
+ {
+ NativeMethods.AllocConsole();
+ InvalidateOutAndError();
+ }
+ //#endif
+ }
+
+ ///
+ /// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
+ ///
+ public static void Hide()
+ {
+ //#if DEBUG
+ if (HasConsole)
+ {
+ SetOutAndErrorNull();
+ NativeMethods.FreeConsole();
+ }
+ //#endif
+ }
+
+ public static void Toggle()
+ {
+ if (HasConsole)
+ {
+ Hide();
+ }
+ else
+ {
+ Show();
+ }
+ }
+
+ static void InvalidateOutAndError()
+ {
+ Type type = typeof(System.Console);
+
+ System.Reflection.FieldInfo _out = type.GetField("_out",
+ System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
+
+ System.Reflection.FieldInfo _error = type.GetField("_error",
+ System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
+
+ System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
+ System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
+
+ System.Diagnostics.Debug.Assert(_out != null);
+ System.Diagnostics.Debug.Assert(_error != null);
+
+ System.Diagnostics.Debug.Assert(_InitializeStdOutError != null);
+
+ _out.SetValue(null, null);
+ _error.SetValue(null, null);
+
+ _InitializeStdOutError.Invoke(null, new object[] { true });
+ }
+
+ static void SetOutAndErrorNull()
+ {
+ Console.SetOut(TextWriter.Null);
+ Console.SetError(TextWriter.Null);
+ }
+ }
+}
+
diff --git a/S7.Net.UnitTest/Helpers/NativeMethods.cs b/S7.Net.UnitTest/Helpers/NativeMethods.cs
new file mode 100644
index 0000000..774136e
--- /dev/null
+++ b/S7.Net.UnitTest/Helpers/NativeMethods.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace S7.Net.UnitTest.Helpers
+{
+
+ internal static class NativeMethods
+ {
+ [StructLayout(LayoutKind.Sequential)]
+ public struct CURSORINFO
+ {
+ public Int32 cbSize;
+ public Int32 flags;
+ public IntPtr hCursor;
+ public POINTAPI ptScreenPos;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct POINTAPI
+ {
+ public int x;
+ public int y;
+ }
+
+ [DllImport("user32.dll")]
+ public static extern int BringWindowToTop(IntPtr hwnd);
+
+ [DllImport("kernel32.dll")]
+ public static extern bool AllocConsole();
+
+ [DllImport("kernel32.dll")]
+ public static extern bool FreeConsole();
+
+ [DllImport("kernel32.dll")]
+ public static extern IntPtr GetConsoleWindow();
+
+ [DllImport("kernel32.dll")]
+ public static extern int GetConsoleOutputCP();
+
+ [DllImport("user32.dll")]
+ public static extern bool GetCursorInfo(out CURSORINFO pci);
+
+ [DllImport("user32.dll")]
+ public static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon);
+ }
+
+}
diff --git a/S7.Net.UnitTest/Helpers/S7TestServer.cs b/S7.Net.UnitTest/Helpers/S7TestServer.cs
new file mode 100644
index 0000000..4a94142
--- /dev/null
+++ b/S7.Net.UnitTest/Helpers/S7TestServer.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Snap7;
+
+namespace S7.Net.UnitTest.Helpers
+{
+ class S7TestServer
+ {
+ static S7Server Server;
+ static private byte[] DB1 = new byte[512]; // Our DB1
+ static private byte[] DB2 = new byte[1028]; // Our DB2
+ static private byte[] DB3 = new byte[1024]; // Our DB3
+ private static S7Server.TSrvCallback TheEventCallBack; // <== Static var containig the callback
+ private static S7Server.TSrvCallback TheReadCallBack; // <== Static var containig the callback
+
+ // Here we use the callback to show the log, this is not the best choice since
+ // the callback is synchronous with the client access, i.e. the server cannot
+ // handle futher request from that client until the callback is complete.
+ // The right choice is to use the log queue via the method PickEvent.
+
+ static void EventCallback(IntPtr usrPtr, ref S7Server.USrvEvent Event, int Size)
+ {
+ Console.WriteLine(Server.EventText(ref Event));
+ }
+
+ static void ReadEventCallback(IntPtr usrPtr, ref S7Server.USrvEvent Event, int Size)
+ {
+ Console.WriteLine(Server.EventText(ref Event));
+ }
+
+ public static void Start()
+ {
+ Server = new S7Server();
+ // Share some resources with our virtual PLC
+ Server.RegisterArea(S7Server.srvAreaDB, // We are registering a DB
+ 1, // Its number is 1 (DB1)
+ DB1, // Our buffer for DB1
+ DB1.Length); // Its size
+ // Do the same for DB2 and DB3
+ Server.RegisterArea(S7Server.srvAreaDB, 2, DB2, DB2.Length);
+ Server.RegisterArea(S7Server.srvAreaDB, 3, DB3, DB3.Length);
+
+ // Exclude read event to avoid the double report
+ // Set the callbacks (using the static var to avoid the garbage collect)
+ TheEventCallBack = new S7Server.TSrvCallback(EventCallback);
+ TheReadCallBack = new S7Server.TSrvCallback(ReadEventCallback);
+
+ Server.EventMask = ~S7Server.evcDataRead;
+ Server.SetEventsCallBack(TheEventCallBack, IntPtr.Zero);
+ Server.SetReadEventsCallBack(TheReadCallBack, IntPtr.Zero);
+
+ // Uncomment next line if you don't want to see wrapped messages
+ // (Note : Doesn't work in Mono 2.10)
+
+ // Console.SetBufferSize(100, Int16.MaxValue - 1);
+
+ // Start the server onto the default adapter.
+ // To select an adapter we have to use Server->StartTo("192.168.x.y").
+ // Start() is the same of StartTo("0.0.0.0");
+ int Error = Server.Start();
+ //if (Error == 0)
+ //{
+ // // Now the server is running ... wait a key to terminate
+ // //Console.ReadKey();
+ // Server.Stop();
+ //}
+ //else
+ // Console.WriteLine(Server.ErrorText(Error));
+ // If you got a start error:
+ // Windows - most likely you ar running the server in a pc on wich is
+ // installed step 7 : open a command prompt and type
+ // "net stop s7oiehsx" (Win32) or
+ // "net stop s7oiehsx64" (Win64)
+ // And after this test :
+ // "net start s7oiehsx" (Win32) or
+ // "net start s7oiehsx64" (Win64)
+ // Unix - you need root rights :-( because the isotcp port (102) is
+ // low and so it's considered "privileged".
+ }
+
+ public static void Stop()
+ {
+ int Error = Server.Stop();
+ }
+ }
+}
diff --git a/S7.Net.UnitTest/Helpers/TestClass.cs b/S7.Net.UnitTest/Helpers/TestClass.cs
new file mode 100644
index 0000000..bb23785
--- /dev/null
+++ b/S7.Net.UnitTest/Helpers/TestClass.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace S7.Net.UnitTest.Helpers
+{
+ class TestClass
+ {
+ ///
+ /// DB1.DBX0.0
+ ///
+ public bool BitVariable00 { get; set; }
+ public bool BitVariable01 { get; set; }
+ public bool BitVariable02 { get; set; }
+ public bool BitVariable03 { get; set; }
+ public bool BitVariable04 { get; set; }
+ public bool BitVariable05 { get; set; }
+ public bool BitVariable06 { get; set; }
+ public bool BitVariable07 { get; set; }
+
+ ///
+ /// DB1.DBX1.0
+ ///
+ public bool BitVariable10 { get; set; }
+ public bool BitVariable11 { get; set; }
+ public bool BitVariable12 { get; set; }
+ public bool BitVariable13 { get; set; }
+ public bool BitVariable14 { get; set; }
+ public bool BitVariable15 { get; set; }
+ public bool BitVariable16 { get; set; }
+ public bool BitVariable17 { get; set; }
+
+ ///
+ /// DB1.DBW2
+ ///
+ public short IntVariable { get; set; }
+
+ ///
+ /// DB1.DBD4
+ ///
+ public double RealVariable { get; set; }
+
+ ///
+ /// DB1.DBD8
+ ///
+ public int DIntVariable { get; set; }
+
+ ///
+ /// DB1.DBD12
+ ///
+ public ushort DWordVariable { get; set; }
+ }
+}
diff --git a/S7.Net.UnitTest/Helpers/TestStruct.cs b/S7.Net.UnitTest/Helpers/TestStruct.cs
new file mode 100644
index 0000000..448e9ce
--- /dev/null
+++ b/S7.Net.UnitTest/Helpers/TestStruct.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace S7.Net.UnitTest.Helpers
+{
+ public struct TestStruct
+ {
+ ///
+ /// DB1.DBX0.0
+ ///
+ public bool BitVariable00;
+ public bool BitVariable01;
+ public bool BitVariable02;
+ public bool BitVariable03;
+ public bool BitVariable04;
+ public bool BitVariable05;
+ public bool BitVariable06;
+ public bool BitVariable07;
+
+ ///
+ /// DB1.DBX1.0
+ ///
+ public bool BitVariable10;
+ public bool BitVariable11;
+ public bool BitVariable12;
+ public bool BitVariable13;
+ public bool BitVariable14;
+ public bool BitVariable15;
+ public bool BitVariable16;
+ public bool BitVariable17;
+
+ ///
+ /// DB1.DBW2
+ ///
+ public short IntVariable;
+
+ ///
+ /// DB1.DBD4
+ ///
+ public double RealVariable;
+
+ ///
+ /// DB1.DBD8
+ ///
+ public int DIntVariable;
+
+ ///
+ /// DB1.DBD12
+ ///
+ public ushort DWordVariable;
+ }
+}
diff --git a/S7.Net.UnitTest/Properties/AssemblyInfo.cs b/S7.Net.UnitTest/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..64fefd7
--- /dev/null
+++ b/S7.Net.UnitTest/Properties/AssemblyInfo.cs
@@ -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.UnitTest")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("S7Net.UnitTest")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[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("6f73e1b1-301b-471e-9f38-3dcbddbcfc21")]
+
+// 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")]
diff --git a/S7.Net.UnitTest/S7.Net.UnitTest.csproj b/S7.Net.UnitTest/S7.Net.UnitTest.csproj
new file mode 100644
index 0000000..9b825a2
--- /dev/null
+++ b/S7.Net.UnitTest/S7.Net.UnitTest.csproj
@@ -0,0 +1,102 @@
+
+
+
+ Debug
+ AnyCPU
+ {303CCED6-9ABC-4899-A509-743341AAA804}
+ Library
+ Properties
+ S7.UnitTest
+ S7Net.UnitTest
+ v4.5
+ 512
+ {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
+ False
+ UnitTest
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+ {bfd484f9-3f04-42a2-bf2a-60a189a25dcf}
+ S7.Net
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/S7.Net.UnitTest/S7NetTests.cs b/S7.Net.UnitTest/S7NetTests.cs
new file mode 100644
index 0000000..c1f7bd5
--- /dev/null
+++ b/S7.Net.UnitTest/S7NetTests.cs
@@ -0,0 +1,207 @@
+#region Using
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using S7.Net;
+using S7.Net.UnitTest.Helpers;
+using S7.Net.UnitTest;
+using System.ServiceProcess;
+
+#endregion
+
+/**
+ * About the tests:
+ * ---------------------------------------------------------------------------
+ * The tests were written to show how to use this library to read and write
+ * different types of values, how to box and unbox values and of course to
+ * address some of the bugs of the library.
+ * These tests are not meant to cover 100% the code, but to check that once a
+ * variable is written, it stores the correct value.
+ * ----------------------------------------------------------------------------
+ * The plc used for the tests is the S7 "server" provided by Snap7 opensource
+ * library, that you can get for free here:http://snap7.sourceforge.net/
+ * The implementation of the server will not be discussed here, but there are
+ * some issues with the interop that cause the server, and unit test, to fail
+ * under some circumstances, like "click on Run all tests" too much.
+ * This doesn't mean that S7.Net has bugs, but that the implementation of the
+ * server has problems.
+ *
+ */
+namespace S7.Net.UnitTest
+{
+ [TestClass]
+ public class S7NetTests
+ {
+ #region Constants
+ const int DB2 = 2;
+ #endregion
+
+ #region Private fields
+ Plc plc;
+ #endregion
+
+ #region Constructor
+ ///
+ /// Create a plc that will connect to localhost (Snap 7 server) and connect to it
+ ///
+ public S7NetTests()
+ {
+ plc = new Plc(CpuType.S7300, "127.0.0.1", 0, 2);
+ //ConsoleManager.Show();
+ ShutDownServiceS7oiehsx64();
+ S7TestServer.Start();
+ plc.Open();
+ }
+
+ #endregion
+
+ #region Tests
+
+ [TestMethod]
+ public void T00_TestConnection()
+ {
+ if (plc.IsConnected == false)
+ {
+ var error = plc.Open();
+ Assert.AreEqual(ErrorCode.NoError, error, "If you have s7 installed you must close s7oiehsx64 service.");
+ }
+ }
+
+ ///
+ /// Read/Write a single Int16 or UInt16 with a single request.
+ /// Test that writing a UInt16 (ushort) and reading it gives the correct value.
+ /// Test also that writing a Int16 (short) and reading it gives the correct value.
+ ///
+ [TestMethod]
+ public void T01_WriteAndReadInt16Variable()
+ {
+ Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
+
+ // To write a ushort i don't need any cast, only unboxing must be done
+ ushort val = 40000;
+ plc.Write("DB1.DBW0", val);
+ ushort result = (ushort)plc.Read("DB1.DBW0");
+ Assert.AreEqual(val, result, "A ushort goes from 0 to 64512");
+
+ // To write a short i need to convert it to UShort, then i need to reconvert the readed value to get
+ // the negative sign back
+ // Depending if i'm writing on a DWORD or on a DEC, i will see ushort or short value in the plc
+ short value = -100;
+ Assert.IsTrue(plc.IsConnected, "After connecting, IsConnected must be set to true");
+ plc.Write("DB1.DBW0", value.ConvertToUshort());
+ short result2 = ((ushort)plc.Read("DB1.DBW0")).ConvertToShort();
+ Assert.AreEqual(value, result2, "A short goes from -32767 to 32766");
+ }
+
+ ///
+ /// Read/Write a single Int32 or UInt32 with a single request.
+ /// Test that writing a UInt32 (uint) and reading it gives the correct value.
+ /// Test also that writing a Int32 (int) and reading it gives the correct value.
+ ///
+ [TestMethod]
+ public void T02_WriteAndReadInt32Variable()
+ {
+ Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
+
+ // To write a uint I don't need any cast, only unboxing must be done
+ uint val = 1000;
+ plc.Write("DB1.DBD40", val);
+ uint result = (uint)plc.Read("DB1.DBD40");
+ Assert.AreEqual(val, result);
+
+ // To write a int I need to convert it to uint, then I need to reconvert the readed value to get
+ // the negative sign back
+ // Depending if I'm writing on a DBD or on a LONG, I will see uint or int value in the plc
+ int value = -60000;
+ plc.Write("DB1.DBD60", value);
+ int result2 = ((uint)plc.Read("DB1.DBD60")).ConvertToInt();
+ Assert.AreEqual(value, result2);
+ }
+
+ ///
+ /// Read/Write a single REAL with a single request.
+ /// Test that writing a double and reading it gives the correct value.
+ ///
+ [TestMethod]
+ public void T03_WriteAndReadRealVariables()
+ {
+ Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
+
+ // Reading and writing a double is quite complicated, because it needs to be converted to DWord before the write,
+ // then reconvert to double after the read.
+ double val = 35.687;
+ plc.Write("DB1.DBD40", val.ConvertToUInt());
+ double result = ((uint)plc.Read("DB1.DBD40")).ConvertToDouble();
+ Assert.AreEqual(val, Math.Round(result, 3)); // float lose precision, so i need to round it
+ }
+
+ ///
+ /// Read/Write a class that has the same properties of a DB with the same field in the same order
+ ///
+ [TestMethod]
+ public void T04_ReadAndWriteClass()
+ {
+ Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
+
+ TestClass tc = new TestClass();
+ tc.BitVariable00 = true;
+ tc.BitVariable10 = true;
+ tc.DIntVariable = -100000;
+ tc.IntVariable = -15000;
+ tc.RealVariable = -154.789;
+ tc.DWordVariable = 850;
+ plc.WriteClass(tc, DB2);
+ TestClass tc2 = new TestClass();
+ // Values that are read from a class are stored inside the class itself, that is passed by reference
+ plc.ReadClass(tc2, DB2);
+ Assert.AreEqual(tc.BitVariable00, tc2.BitVariable00);
+ Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
+ Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
+ Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
+ Assert.AreEqual(tc.RealVariable, Math.Round(tc2.RealVariable, 3));
+ Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
+ }
+
+ ///
+ /// Read/Write a struct that has the same properties of a DB with the same field in the same order
+ ///
+ [TestMethod]
+ public void T05_ReadAndWriteStruct()
+ {
+ Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor.");
+
+ TestStruct tc = new TestStruct();
+ tc.BitVariable00 = true;
+ tc.BitVariable10 = true;
+ tc.DIntVariable = -100000;
+ tc.IntVariable = -15000;
+ tc.RealVariable = -154.789;
+ tc.DWordVariable = 850;
+ plc.WriteStruct(tc, DB2);
+ // Values that are read from a struct are stored in a new struct, returned by the funcion ReadStruct
+ TestStruct tc2 = (TestStruct)plc.ReadStruct(typeof(TestStruct), DB2);
+ Assert.AreEqual(tc.BitVariable00, tc2.BitVariable00);
+ Assert.AreEqual(tc.BitVariable10, tc2.BitVariable10);
+ Assert.AreEqual(tc.DIntVariable, tc2.DIntVariable);
+ Assert.AreEqual(tc.IntVariable, tc2.IntVariable);
+ Assert.AreEqual(tc.RealVariable, Math.Round(tc2.RealVariable, 3));
+ Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable);
+ }
+
+ #endregion
+
+ #region Private methods
+
+ private static void ShutDownServiceS7oiehsx64()
+ {
+ ServiceController sc = new ServiceController("s7oiehsx64");
+ switch (sc.Status)
+ {
+ case ServiceControllerStatus.Running:
+ sc.Stop();
+ break;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/S7.Net.UnitTest/Snap7/snap7.net.cs b/S7.Net.UnitTest/Snap7/snap7.net.cs
new file mode 100644
index 0000000..98efa75
--- /dev/null
+++ b/S7.Net.UnitTest/Snap7/snap7.net.cs
@@ -0,0 +1,2018 @@
+/*=============================================================================|
+| PROJECT SNAP7 1.2.0 |
+|==============================================================================|
+| Copyright (C) 2013, 2014 Davide Nardella |
+| All rights reserved. |
+|==============================================================================|
+| SNAP7 is free software: you can redistribute it and/or modify |
+| it under the terms of the Lesser GNU General Public License as published by |
+| the Free Software Foundation, either version 3 of the License, or |
+| (at your option) any later version. |
+| |
+| It means that you can distribute your commercial software linked with |
+| SNAP7 without the requirement to distribute the source code of your |
+| application and without the requirement that your application be itself |
+| distributed under LGPL. |
+| |
+| SNAP7 is distributed in the hope that it will be useful, |
+| but WITHOUT ANY WARRANTY; without even the implied warranty of |
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+| Lesser GNU General Public License for more details. |
+| |
+| You should have received a copy of the GNU General Public License and a |
+| copy of Lesser GNU General Public License along with Snap7. |
+| If not, see http://www.gnu.org/licenses/ |
+|==============================================================================|
+| |
+| C# Interface classes. |
+| |
+|=============================================================================*/
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Snap7
+{
+
+ public class S7Consts
+ {
+ #if __MonoCS__ // Assuming that we are using Unix release of Mono (otherwise modify it)
+ public const string Snap7LibName = "libsnap7.so";
+ #else
+ public const string Snap7LibName = "snap7.dll";
+ #endif
+ //------------------------------------------------------------------------------
+ // PARAMS LIST
+ //------------------------------------------------------------------------------
+ public static readonly Int32 p_u16_LocalPort = 1;
+ public static readonly Int32 p_u16_RemotePort = 2;
+ public static readonly Int32 p_i32_PingTimeout = 3;
+ public static readonly Int32 p_i32_SendTimeout = 4;
+ public static readonly Int32 p_i32_RecvTimeout = 5;
+ public static readonly Int32 p_i32_WorkInterval = 6;
+ public static readonly Int32 p_u16_SrcRef = 7;
+ public static readonly Int32 p_u16_DstRef = 8;
+ public static readonly Int32 p_u16_SrcTSap = 9;
+ public static readonly Int32 p_i32_PDURequest = 10;
+ public static readonly Int32 p_i32_MaxClients = 11;
+ public static readonly Int32 p_i32_BSendTimeout = 12;
+ public static readonly Int32 p_i32_BRecvTimeout = 13;
+ public static readonly Int32 p_u32_RecoveryTime = 14;
+ public static readonly Int32 p_u32_KeepAliveTime = 15;
+ }
+
+ public class S7Client
+ {
+ #region [Constants, private vars and TypeDefs]
+ private const int MsgTextLen = 1024;
+ // Error codes
+ public static readonly uint errNegotiatingPDU = 0x00100000;
+ public static readonly uint errCliInvalidParams = 0x00200000;
+ public static readonly uint errCliJobPending = 0x00300000;
+ public static readonly uint errCliTooManyItems = 0x00400000;
+ public static readonly uint errCliInvalidWordLen = 0x00500000;
+ public static readonly uint errCliPartialDataWritten = 0x00600000;
+ public static readonly uint errCliSizeOverPDU = 0x00700000;
+ public static readonly uint errCliInvalidPlcAnswer = 0x00800000;
+ public static readonly uint errCliAddressOutOfRange = 0x00900000;
+ public static readonly uint errCliInvalidTransportSize = 0x00A00000;
+ public static readonly uint errCliWriteDataSizeMismatch = 0x00B00000;
+ public static readonly uint errCliItemNotAvailable = 0x00C00000;
+ public static readonly uint errCliInvalidValue = 0x00D00000;
+ public static readonly uint errCliCannotStartPLC = 0x00E00000;
+ public static readonly uint errCliAlreadyRun = 0x00F00000;
+ public static readonly uint errCliCannotStopPLC = 0x01000000;
+ public static readonly uint errCliCannotCopyRamToRom = 0x01100000;
+ public static readonly uint errCliCannotCompress = 0x01200000;
+ public static readonly uint errCliAlreadyStop = 0x01300000;
+ public static readonly uint errCliFunNotAvailable = 0x01400000;
+ public static readonly uint errCliUploadSequenceFailed = 0x01500000;
+ public static readonly uint errCliInvalidDataSizeRecvd = 0x01600000;
+ public static readonly uint errCliInvalidBlockType = 0x01700000;
+ public static readonly uint errCliInvalidBlockNumber = 0x01800000;
+ public static readonly uint errCliInvalidBlockSize = 0x01900000;
+ public static readonly uint errCliDownloadSequenceFailed = 0x01A00000;
+ public static readonly uint errCliInsertRefused = 0x01B00000;
+ public static readonly uint errCliDeleteRefused = 0x01C00000;
+ public static readonly uint errCliNeedPassword = 0x01D00000;
+ public static readonly uint errCliInvalidPassword = 0x01E00000;
+ public static readonly uint errCliNoPasswordToSetOrClear = 0x01F00000;
+ public static readonly uint errCliJobTimeout = 0x02000000;
+ public static readonly uint errCliPartialDataRead = 0x02100000;
+ public static readonly uint errCliBufferTooSmall = 0x02200000;
+ public static readonly uint errCliFunctionRefused = 0x02300000;
+ public static readonly uint errCliDestroying = 0x02400000;
+ public static readonly uint errCliInvalidParamNumber = 0x02500000;
+ public static readonly uint errCliCannotChangeParam = 0x02600000;
+
+ // Area ID
+ public static readonly byte S7AreaPE = 0x81;
+ public static readonly byte S7AreaPA = 0x82;
+ public static readonly byte S7AreaMK = 0x83;
+ public static readonly byte S7AreaDB = 0x84;
+ public static readonly byte S7AreaCT = 0x1C;
+ public static readonly byte S7AreaTM = 0x1D;
+
+ // Word Length
+ public static readonly int S7WLBit = 0x01;
+ public static readonly int S7WLByte = 0x02;
+ public static readonly int S7WLWord = 0x04;
+ public static readonly int S7WLDWord = 0x06;
+ public static readonly int S7WLReal = 0x08;
+ public static readonly int S7WLCounter = 0x1C;
+ public static readonly int S7WLTimer = 0x1D;
+
+ // Block type
+ public static readonly byte Block_OB = 0x38;
+ public static readonly byte Block_DB = 0x41;
+ public static readonly byte Block_SDB = 0x42;
+ public static readonly byte Block_FC = 0x43;
+ public static readonly byte Block_SFC = 0x44;
+ public static readonly byte Block_FB = 0x45;
+ public static readonly byte Block_SFB = 0x46;
+
+ // Sub Block Type
+ public static readonly byte SubBlk_OB = 0x08;
+ public static readonly byte SubBlk_DB = 0x0A;
+ public static readonly byte SubBlk_SDB = 0x0B;
+ public static readonly byte SubBlk_FC = 0x0C;
+ public static readonly byte SubBlk_SFC = 0x0D;
+ public static readonly byte SubBlk_FB = 0x0E;
+ public static readonly byte SubBlk_SFB = 0x0F;
+
+ // Block languages
+ public static readonly byte BlockLangAWL = 0x01;
+ public static readonly byte BlockLangKOP = 0x02;
+ public static readonly byte BlockLangFUP = 0x03;
+ public static readonly byte BlockLangSCL = 0x04;
+ public static readonly byte BlockLangDB = 0x05;
+ public static readonly byte BlockLangGRAPH = 0x06;
+
+ // Max number of vars (multiread/write)
+ public static readonly int MaxVars = 20;
+
+ // Client Connection Type
+ public static readonly UInt16 CONNTYPE_PG = 0x01; // Connect to the PLC as a PG
+ public static readonly UInt16 CONNTYPE_OP = 0x02; // Connect to the PLC as an OP
+ public static readonly UInt16 CONNTYPE_BASIC = 0x03; // Basic connection
+
+ // Job
+ private const int JobComplete = 0;
+ private const int JobPending = 1;
+
+ private IntPtr Client;
+
+ // Data Item
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct S7DataItem
+ {
+ public Int32 Area;
+ public Int32 WordLen;
+ public Int32 Result;
+ public Int32 DBNumber;
+ public Int32 Start;
+ public Int32 Amount;
+ public IntPtr pData;
+ }
+
+ // Block List
+ [StructLayout(LayoutKind.Sequential, Pack = 1)] // <- "maybe" we don't need
+ public struct S7BlocksList
+ {
+ public Int32 OBCount;
+ public Int32 FBCount;
+ public Int32 FCCount;
+ public Int32 SFBCount;
+ public Int32 SFCCount;
+ public Int32 DBCount;
+ public Int32 SDBCount;
+ };
+
+ // Packed Block Info
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
+ protected struct US7BlockInfo
+ {
+ public Int32 BlkType;
+ public Int32 BlkNumber;
+ public Int32 BlkLang;
+ public Int32 BlkFlags;
+ public Int32 MC7Size; // The real size in bytes
+ public Int32 LoadSize;
+ public Int32 LocalData;
+ public Int32 SBBLength;
+ public Int32 CheckSum;
+ public Int32 Version;
+ // Chars info
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
+ public char[] CodeDate;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
+ public char[] IntfDate;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
+ public char[] Author;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
+ public char[] Family;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
+ public char[] Header;
+ };
+ private US7BlockInfo UBlockInfo;
+
+ // Managed Block Info
+ public struct S7BlockInfo
+ {
+ public int BlkType;
+ public int BlkNumber;
+ public int BlkLang;
+ public int BlkFlags;
+ public int MC7Size; // The real size in bytes
+ public int LoadSize;
+ public int LocalData;
+ public int SBBLength;
+ public int CheckSum;
+ public int Version;
+ // Chars info
+ public string CodeDate;
+ public string IntfDate;
+ public string Author;
+ public string Family;
+ public string Header;
+ };
+
+
+ public ushort[] TS7BlocksOfType;
+
+ // Packed Order Code + Version
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
+ protected struct US7OrderCode
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)]
+ public char[] Code;
+ public byte V1;
+ public byte V2;
+ public byte V3;
+ };
+ private US7OrderCode UOrderCode;
+
+ // Managed Order Code + Version
+ public struct S7OrderCode
+ {
+ public string Code;
+ public byte V1;
+ public byte V2;
+ public byte V3;
+ };
+
+ // Packed CPU Info
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
+ protected struct US7CpuInfo
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 33)]
+ public char[] ModuleTypeName;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)]
+ public char[] SerialNumber;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)]
+ public char[] ASName;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 27)]
+ public char[] Copyright;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)]
+ public char[] ModuleName;
+ };
+ private US7CpuInfo UCpuInfo;
+
+ // Managed CPU Info
+ public struct S7CpuInfo
+ {
+ public string ModuleTypeName;
+ public string SerialNumber;
+ public string ASName;
+ public string Copyright;
+ public string ModuleName;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct S7CpInfo
+ {
+ public Int32 MaxPduLengt;
+ public Int32 MaxConnections;
+ public Int32 MaxMpiRate;
+ public Int32 MaxBusRate;
+ };
+
+ // See §33.1 of "System Software for S7-300/400 System and Standard Functions"
+ // and see SFC51 description too
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct SZL_HEADER
+ {
+ public UInt16 LENTHDR;
+ public UInt16 N_DR;
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct S7SZL
+ {
+ public SZL_HEADER Header;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x4000 - 4)]
+ public byte[] Data;
+ };
+
+ // SZL List of available SZL IDs : same as SZL but List items are big-endian adjusted
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct S7SZLList
+ {
+ public SZL_HEADER Header;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x2000 - 2)]
+ public UInt16[] Data;
+ };
+
+ // S7 Protection
+ // See §33.19 of "System Software for S7-300/400 System and Standard Functions"
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct S7Protection // Packed S7Protection
+ {
+ public UInt16 sch_schal;
+ public UInt16 sch_par;
+ public UInt16 sch_rel;
+ public UInt16 bart_sch;
+ public UInt16 anl_sch;
+ };
+
+ // C++ time struct, functions to convert it from/to DateTime are provided ;-)
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ protected struct cpp_tm
+ {
+ public Int32 tm_sec;
+ public Int32 tm_min;
+ public Int32 tm_hour;
+ public Int32 tm_mday;
+ public Int32 tm_mon;
+ public Int32 tm_year;
+ public Int32 tm_wday;
+ public Int32 tm_yday;
+ public Int32 tm_isdst;
+ }
+ private cpp_tm tm;
+
+ #endregion
+
+ #region [Class Control]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern IntPtr Cli_Create();
+ public S7Client()
+ {
+ Client = Cli_Create();
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_Destroy(ref IntPtr Client);
+ ~S7Client()
+ {
+ Cli_Destroy(ref Client);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_Connect(IntPtr Client);
+ public int Connect()
+ {
+ return Cli_Connect(Client);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ConnectTo(IntPtr Client,
+ [MarshalAs(UnmanagedType.LPStr)] string Address,
+ int Rack,
+ int Slot
+ );
+
+ public int ConnectTo(string Address, int Rack, int Slot)
+ {
+ return Cli_ConnectTo(Client, Address, Rack, Slot);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_SetConnectionParams(IntPtr Client,
+ [MarshalAs(UnmanagedType.LPStr)] string Address,
+ UInt16 LocalTSAP,
+ UInt16 RemoteTSAP
+ );
+
+ public int SetConnectionParams(string Address, UInt16 LocalTSAP, UInt16 RemoteTSAP)
+ {
+ return Cli_SetConnectionParams(Client, Address, LocalTSAP, RemoteTSAP);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_SetConnectionType(IntPtr Client, UInt16 ConnectionType);
+ public int SetConnectionType(UInt16 ConnectionType)
+ {
+ return Cli_SetConnectionType(Client, ConnectionType);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_Disconnect(IntPtr Client);
+ public int Disconnect()
+ {
+ return Cli_Disconnect(Client);
+ }
+
+ // Get/SetParam needs a void* parameter, internally it decides the kind of pointer
+ // in accord to ParamNumber.
+ // To avoid the use of unsafe code we split the DLL functions and use overloaded methods.
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_GetParam")]
+ protected static extern int Cli_GetParam_i16(IntPtr Client, Int32 ParamNumber, ref Int16 IntValue);
+ public int GetParam(Int32 ParamNumber, ref Int16 IntValue)
+ {
+ return Cli_GetParam_i16(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_GetParam")]
+ protected static extern int Cli_GetParam_u16(IntPtr Client, Int32 ParamNumber, ref UInt16 IntValue);
+ public int GetParam(Int32 ParamNumber, ref UInt16 IntValue)
+ {
+ return Cli_GetParam_u16(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_GetParam")]
+ protected static extern int Cli_GetParam_i32(IntPtr Client, Int32 ParamNumber, ref Int32 IntValue);
+ public int GetParam(Int32 ParamNumber, ref Int32 IntValue)
+ {
+ return Cli_GetParam_i32(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_GetParam")]
+ protected static extern int Cli_GetParam_u32(IntPtr Client, Int32 ParamNumber, ref UInt32 IntValue);
+ public int GetParam(Int32 ParamNumber, ref UInt32 IntValue)
+ {
+ return Cli_GetParam_u32(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_GetParam")]
+ protected static extern int Cli_GetParam_i64(IntPtr Client, Int32 ParamNumber, ref Int64 IntValue);
+ public int GetParam(Int32 ParamNumber, ref Int64 IntValue)
+ {
+ return Cli_GetParam_i64(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_GetParam")]
+ protected static extern int Cli_GetParam_u64(IntPtr Client, Int32 ParamNumber, ref UInt64 IntValue);
+ public int GetParam(Int32 ParamNumber, ref UInt64 IntValue)
+ {
+ return Cli_GetParam_u64(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_SetParam")]
+ protected static extern int Cli_SetParam_i16(IntPtr Client, Int32 ParamNumber, ref Int16 IntValue);
+ public int SetParam(Int32 ParamNumber, ref Int16 IntValue)
+ {
+ return Cli_SetParam_i16(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_SetParam")]
+ protected static extern int Cli_SetParam_u16(IntPtr Client, Int32 ParamNumber, ref UInt16 IntValue);
+ public int SetParam(Int32 ParamNumber, ref UInt16 IntValue)
+ {
+ return Cli_SetParam_u16(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_SetParam")]
+ protected static extern int Cli_SetParam_i32(IntPtr Client, Int32 ParamNumber, ref Int32 IntValue);
+ public int SetParam(Int32 ParamNumber, ref Int32 IntValue)
+ {
+ return Cli_SetParam_i32(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_SetParam")]
+ protected static extern int Cli_SetParam_u32(IntPtr Client, Int32 ParamNumber, ref UInt32 IntValue);
+ public int SetParam(Int32 ParamNumber, ref UInt32 IntValue)
+ {
+ return Cli_SetParam_u32(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_SetParam")]
+ protected static extern int Cli_SetParam_i64(IntPtr Client, Int32 ParamNumber, ref Int64 IntValue);
+ public int SetParam(Int32 ParamNumber, ref Int64 IntValue)
+ {
+ return Cli_SetParam_i64(Client, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Cli_SetParam")]
+ protected static extern int Cli_SetParam_u64(IntPtr Client, Int32 ParamNumber, ref UInt64 IntValue);
+ public int SetParam(Int32 ParamNumber, ref UInt64 IntValue)
+ {
+ return Cli_SetParam_u64(Client, ParamNumber, ref IntValue);
+ }
+
+ public delegate void S7CliCompletion(IntPtr usrPtr, int opCode, int opResult);
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_SetAsCallback(IntPtr Client, S7CliCompletion Completion, IntPtr usrPtr);
+ public int SetAsCallBack(S7CliCompletion Completion, IntPtr usrPtr)
+ {
+ return Cli_SetAsCallback(Client, Completion, usrPtr);
+ }
+
+ #endregion
+
+ #region [Data I/O main functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ReadArea(IntPtr Client, int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer);
+ public int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer)
+ {
+ return Cli_ReadArea(Client, Area, DBNumber, Start, Amount, WordLen, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_WriteArea(IntPtr Client, int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer);
+ public int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer)
+ {
+ return Cli_WriteArea(Client, Area, DBNumber, Start, Amount, WordLen, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ReadMultiVars(IntPtr Client, ref S7DataItem Item, int ItemsCount);
+ public int ReadMultiVars(ref S7DataItem Item, int ItemsCount)
+ {
+ return Cli_ReadMultiVars(Client, ref Item, ItemsCount);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_WriteMultiVars(IntPtr Client, ref S7DataItem Item, int ItemsCount);
+ public int WriteMultiVars(ref S7DataItem Item, int ItemsCount)
+ {
+ return Cli_WriteMultiVars(Client, ref Item, ItemsCount);
+ }
+
+ #endregion
+
+ #region [Data I/O lean functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_DBRead(IntPtr Client, int DBNumber, int Start, int Size, byte[] Buffer);
+ public int DBRead(int DBNumber, int Start, int Size, byte[] Buffer)
+ {
+ return Cli_DBRead(Client, DBNumber, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_DBWrite(IntPtr Client, int DBNumber, int Start, int Size, byte[] Buffer);
+ public int DBWrite(int DBNumber, int Start, int Size, byte[] Buffer)
+ {
+ return Cli_DBWrite(Client, DBNumber, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_MBRead(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int MBRead(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_MBRead(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_MBWrite(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int MBWrite(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_MBWrite(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_EBRead(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int EBRead(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_EBRead(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_EBWrite(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int EBWrite(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_EBWrite(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ABRead(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int ABRead(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_ABRead(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ABWrite(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int ABWrite(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_ABWrite(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_TMRead(IntPtr Client, int Start, int Amount, ushort[] Buffer);
+ public int TMRead(int Start, int Amount, ushort[] Buffer)
+ {
+ return Cli_TMRead(Client, Start, Amount, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_TMWrite(IntPtr Client, int Start, int Amount, ushort[] Buffer);
+ public int TMWrite(int Start, int Amount, ushort[] Buffer)
+ {
+ return Cli_TMWrite(Client, Start, Amount, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_CTRead(IntPtr Client, int Start, int Amount, ushort[] Buffer);
+ public int CTRead(int Start, int Amount, ushort[] Buffer)
+ {
+ return Cli_CTRead(Client, Start, Amount, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_CTWrite(IntPtr Client, int Start, int Amount, ushort[] Buffer);
+ public int CTWrite(int Start, int Amount, ushort[] Buffer)
+ {
+ return Cli_CTWrite(Client, Start, Amount, Buffer);
+ }
+
+ #endregion
+
+ #region [Directory functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ListBlocks(IntPtr Client, ref S7BlocksList List);
+ public int ListBlocks(ref S7BlocksList List)
+ {
+ return Cli_ListBlocks(Client, ref List);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetAgBlockInfo(IntPtr Client, int BlockType, int BlockNum, ref US7BlockInfo Info);
+ public int GetAgBlockInfo(IntPtr Client, int BlockType, int BlockNum, ref S7BlockInfo Info)
+ {
+ int res = Cli_GetAgBlockInfo(Client, BlockType, BlockNum, ref UBlockInfo);
+ // Packed->Managed
+ if (res == 0)
+ {
+ Info.BlkType = UBlockInfo.BlkType;
+ Info.BlkNumber = UBlockInfo.BlkNumber;
+ Info.BlkLang = UBlockInfo.BlkLang;
+ Info.BlkFlags = UBlockInfo.BlkFlags;
+ Info.MC7Size = UBlockInfo.MC7Size;
+ Info.LoadSize = UBlockInfo.LoadSize;
+ Info.LocalData = UBlockInfo.LocalData;
+ Info.SBBLength = UBlockInfo.SBBLength;
+ Info.CheckSum = UBlockInfo.CheckSum;
+ Info.Version = UBlockInfo.Version;
+ // Chars info
+ Info.CodeDate = new string(UBlockInfo.CodeDate);
+ Info.IntfDate = new string(UBlockInfo.IntfDate);
+ Info.Author = new string(UBlockInfo.Author);
+ Info.Family = new string(UBlockInfo.Family);
+ Info.Header = new string(UBlockInfo.Header);
+ }
+ return res;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetPgBlockInfo(IntPtr Client, ref US7BlockInfo Info, byte[] Buffer, Int32 Size);
+ public int GetPgBlockInfo(ref S7BlockInfo Info, byte[] Buffer, int Size)
+ {
+ int res = Cli_GetPgBlockInfo(Client, ref UBlockInfo, Buffer, Size);
+ // Packed->Managed
+ if (res == 0)
+ {
+ Info.BlkType = UBlockInfo.BlkType;
+ Info.BlkNumber = UBlockInfo.BlkNumber;
+ Info.BlkLang = UBlockInfo.BlkLang;
+ Info.BlkFlags = UBlockInfo.BlkFlags;
+ Info.MC7Size = UBlockInfo.MC7Size;
+ Info.LoadSize = UBlockInfo.LoadSize;
+ Info.LocalData = UBlockInfo.LocalData;
+ Info.SBBLength = UBlockInfo.SBBLength;
+ Info.CheckSum = UBlockInfo.CheckSum;
+ Info.Version = UBlockInfo.Version;
+ // Chars info
+ Info.CodeDate = new string(UBlockInfo.CodeDate);
+ Info.IntfDate = new string(UBlockInfo.IntfDate);
+ Info.Author = new string(UBlockInfo.Author);
+ Info.Family = new string(UBlockInfo.Family);
+ Info.Header = new string(UBlockInfo.Header);
+ }
+ return res;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ListBlocksOfType(IntPtr Client, Int32 BlockType, ushort[] List, ref int ItemsCount);
+ public int ListBlocksOfType(int BlockType, ushort[] List, ref int ItemsCount)
+ {
+ return Cli_ListBlocksOfType(Client, BlockType, List, ref ItemsCount);
+ }
+
+ #endregion
+
+ #region [Blocks functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_Upload(IntPtr Client, int BlockType, int BlockNum, byte[] UsrData, ref int Size);
+ public int Upload(int BlockType, int BlockNum, byte[] UsrData, ref int Size)
+ {
+ return Cli_Upload(Client, BlockType, BlockNum, UsrData, ref Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_FullUpload(IntPtr Client, int BlockType, int BlockNum, byte[] UsrData, ref int Size);
+ public int FullUpload(int BlockType, int BlockNum, byte[] UsrData, ref int Size)
+ {
+ return Cli_FullUpload(Client, BlockType, BlockNum, UsrData, ref Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_Download(IntPtr Client, int BlockNum, byte[] UsrData, int Size);
+ public int Download(int BlockNum, byte[] UsrData, int Size)
+ {
+ return Cli_Download(Client, BlockNum, UsrData, Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_Delete(IntPtr Client, int BlockType, int BlockNum);
+ public int Delete(int BlockType, int BlockNum)
+ {
+ return Cli_Delete(Client, BlockType, BlockNum);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_DBGet(IntPtr Client, int DBNumber, byte[] UsrData, ref int Size);
+ public int DBGet(int DBNumber, byte[] UsrData, ref int Size)
+ {
+ return Cli_DBGet(Client, DBNumber, UsrData, ref Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_DBFill(IntPtr Client, int DBNumber, int FillChar);
+ public int DBFill(int DBNumber, int FillChar)
+ {
+ return Cli_DBFill(Client, DBNumber, FillChar);
+ }
+
+ #endregion
+
+ #region [Date/Time functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetPlcDateTime(IntPtr Client, ref cpp_tm tm);
+ public int GetPlcDateTime(ref DateTime DT)
+ {
+ int res = Cli_GetPlcDateTime(Client, ref tm);
+ if (res == 0)
+ {
+ // Packed->Managed
+ DateTime PlcDT = new DateTime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+ DT = PlcDT;
+ }
+ return res;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_SetPlcDateTime(IntPtr Client, ref cpp_tm tm);
+ public int SetPlcDateTime(DateTime DT)
+ {
+
+ // Managed->Packed
+ tm.tm_year = DT.Year - 1900;
+ tm.tm_mon = DT.Month-1;
+ tm.tm_mday = DT.Day;
+ tm.tm_hour = DT.Hour;
+ tm.tm_min = DT.Minute;
+ tm.tm_sec = DT.Second;
+
+ return Cli_SetPlcDateTime(Client, ref tm);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_SetPlcSystemDateTime(IntPtr Client);
+ public int SetPlcSystemDateTime()
+ {
+ return Cli_SetPlcSystemDateTime(Client);
+ }
+
+ #endregion
+
+ #region [System Info functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetOrderCode(IntPtr Client, ref US7OrderCode Info);
+ public int GetOrderCode(ref S7OrderCode Info)
+ {
+ int res = Cli_GetOrderCode(Client, ref UOrderCode);
+ // Packed->Managed
+ if (res == 0)
+ {
+ Info.Code = new string(UOrderCode.Code);
+ Info.V1 = UOrderCode.V1;
+ Info.V2 = UOrderCode.V2;
+ Info.V3 = UOrderCode.V3;
+ }
+ return res;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetCpuInfo(IntPtr Client, ref US7CpuInfo Info);
+ public int GetCpuInfo(ref S7CpuInfo Info)
+ {
+ int res = Cli_GetCpuInfo(Client, ref UCpuInfo);
+ // Packed->Managed
+ if (res == 0)
+ {
+ Info.ModuleTypeName = new string(UCpuInfo.ModuleTypeName);
+ Info.SerialNumber = new string(UCpuInfo.SerialNumber);
+ Info.ASName = new string(UCpuInfo.ASName);
+ Info.Copyright = new string(UCpuInfo.Copyright);
+ Info.ModuleName = new string(UCpuInfo.ModuleName);
+ }
+ return res;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetCpInfo(IntPtr Client, ref S7CpInfo Info);
+
+ public int GetCpInfo(ref S7CpInfo Info)
+ {
+ return Cli_GetCpInfo(Client, ref Info);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ReadSZL(IntPtr Client, int ID, int Index, ref S7SZL Data, ref Int32 Size);
+ public int ReadSZL(int ID, int Index, ref S7SZL Data, ref Int32 Size)
+ {
+ return Cli_ReadSZL(Client, ID, Index, ref Data, ref Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ReadSZLList(IntPtr Client, ref S7SZLList List, ref Int32 ItemsCount);
+ public int ReadSZLList(ref S7SZLList List, ref Int32 ItemsCount)
+ {
+ return Cli_ReadSZLList(Client, ref List, ref ItemsCount);
+ }
+
+ #endregion
+
+ #region [Control functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_PlcHotStart(IntPtr Client);
+ public int PlcHotStart()
+ {
+ return Cli_PlcHotStart(Client);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_PlcColdStart(IntPtr Client);
+ public int PlcColdStart()
+ {
+ return Cli_PlcColdStart(Client);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_PlcStop(IntPtr Client);
+ public int PlcStop()
+ {
+ return Cli_PlcStop(Client);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_CopyRamToRom(IntPtr Client, UInt32 Timeout);
+ public int PlcCopyRamToRom(UInt32 Timeout)
+ {
+ return Cli_CopyRamToRom(Client, Timeout);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_Compress(IntPtr Client, UInt32 Timeout);
+ public int PlcCompress(UInt32 Timeout)
+ {
+ return Cli_Compress(Client, Timeout);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetPlcStatus(IntPtr Client, ref Int32 Status);
+ public int PlcGetStatus(ref Int32 Status)
+ {
+ return Cli_GetPlcStatus(Client, ref Status);
+ }
+
+ #endregion
+
+ #region [Security functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetProtection(IntPtr Client, ref S7Protection Protection);
+ public int GetProtection(ref S7Protection Protection)
+ {
+ return Cli_GetProtection(Client, ref Protection);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_SetSessionPassword(IntPtr Client, [MarshalAs(UnmanagedType.LPStr)] string Password);
+ public int SetSessionPassword(string Password)
+ {
+ return Cli_SetSessionPassword(Client, Password);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_ClearSessionPassword(IntPtr Client);
+ public int ClearSessionPassword()
+ {
+ return Cli_ClearSessionPassword(Client);
+ }
+
+ #endregion
+
+ #region [Low Level]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_IsoExchangeBuffer(IntPtr Client, byte[] Buffer, ref Int32 Size);
+ public int IsoExchangeBuffer(byte[] Buffer, ref Int32 Size)
+ {
+ return Cli_IsoExchangeBuffer(Client, Buffer, ref Size);
+ }
+
+ #endregion
+
+ #region [Async functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsReadArea(IntPtr Client, int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer);
+ public int AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer)
+ {
+ return Cli_AsReadArea(Client, Area, DBNumber, Start, Amount, WordLen, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsWriteArea(IntPtr Client, int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer);
+ public int AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer)
+ {
+ return Cli_AsWriteArea(Client, Area, DBNumber, Start, Amount, WordLen, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsDBRead(IntPtr Client, int DBNumber, int Start, int Size, byte[] Buffer);
+ public int AsDBRead(int DBNumber, int Start, int Size, byte[] Buffer)
+ {
+ return Cli_AsDBRead(Client, DBNumber, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsDBWrite(IntPtr Client, int DBNumber, int Start, int Size, byte[] Buffer);
+ public int AsDBWrite(int DBNumber, int Start, int Size, byte[] Buffer)
+ {
+ return Cli_AsDBWrite(Client, DBNumber, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsMBRead(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int AsMBRead(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_AsMBRead(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsMBWrite(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int AsMBWrite(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_AsMBWrite(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsEBRead(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int AsEBRead(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_AsEBRead(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsEBWrite(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int AsEBWrite(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_AsEBWrite(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsABRead(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int AsABRead(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_AsABRead(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsABWrite(IntPtr Client, int Start, int Size, byte[] Buffer);
+ public int AsABWrite(int Start, int Size, byte[] Buffer)
+ {
+ return Cli_AsABWrite(Client, Start, Size, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsTMRead(IntPtr Client, int Start, int Amount, ushort[] Buffer);
+ public int AsTMRead(int Start, int Amount, ushort[] Buffer)
+ {
+ return Cli_AsTMRead(Client, Start, Amount, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsTMWrite(IntPtr Client, int Start, int Amount, ushort[] Buffer);
+ public int AsTMWrite(int Start, int Amount, ushort[] Buffer)
+ {
+ return Cli_AsTMWrite(Client, Start, Amount, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsCTRead(IntPtr Client, int Start, int Amount, ushort[] Buffer);
+ public int AsCTRead(int Start, int Amount, ushort[] Buffer)
+ {
+ return Cli_AsCTRead(Client, Start, Amount, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsCTWrite(IntPtr Client, int Start, int Amount, ushort[] Buffer);
+ public int AsCTWrite(int Start, int Amount, ushort[] Buffer)
+ {
+ return Cli_AsCTWrite(Client, Start, Amount, Buffer);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsListBlocksOfType(IntPtr Client, Int32 BlockType, ushort[] List);
+ public int AsListBlocksOfType(int BlockType, ushort[] List)
+ {
+ return Cli_AsListBlocksOfType(Client, BlockType, List);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsReadSZL(IntPtr Client, int ID, int Index, ref S7SZL Data, ref Int32 Size);
+ public int AsReadSZL(int ID, int Index, ref S7SZL Data, ref Int32 Size)
+ {
+ return Cli_AsReadSZL(Client, ID, Index, ref Data, ref Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsReadSZLList(IntPtr Client, ref S7SZLList List, ref Int32 ItemsCount);
+ public int AsReadSZLList(ref S7SZLList List, ref Int32 ItemsCount)
+ {
+ return Cli_AsReadSZLList(Client, ref List, ref ItemsCount);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsUpload(IntPtr Client, int BlockType, int BlockNum, byte[] UsrData, ref int Size);
+ public int AsUpload(int BlockType, int BlockNum, byte[] UsrData, ref int Size)
+ {
+ return Cli_AsUpload(Client, BlockType, BlockNum, UsrData, ref Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsFullUpload(IntPtr Client, int BlockType, int BlockNum, byte[] UsrData, ref int Size);
+ public int AsFullUpload(int BlockType, int BlockNum, byte[] UsrData, ref int Size)
+ {
+ return Cli_AsFullUpload(Client, BlockType, BlockNum, UsrData, ref Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsDownload(IntPtr Client, int BlockNum, byte[] UsrData, int Size);
+ public int ASDownload(int BlockNum, byte[] UsrData, int Size)
+ {
+ return Cli_AsDownload(Client, BlockNum, UsrData, Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsPlcCopyRamToRom(IntPtr Client, UInt32 Timeout);
+ public int AsPlcCopyRamToRom(UInt32 Timeout)
+ {
+ return Cli_AsPlcCopyRamToRom(Client, Timeout);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsPlcCompress(IntPtr Client, UInt32 Timeout);
+ public int AsPlcCompress(UInt32 Timeout)
+ {
+ return Cli_AsPlcCompress(Client, Timeout);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsDBGet(IntPtr Client, int DBNumber, byte[] UsrData, ref int Size);
+ public int AsDBGet(int DBNumber, byte[] UsrData, ref int Size)
+ {
+ return Cli_AsDBGet(Client, DBNumber, UsrData, ref Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_AsDBFill(IntPtr Client, int DBNumber, int FillChar);
+ public int AsDBFill(int DBNumber, int FillChar)
+ {
+ return Cli_AsDBFill(Client, DBNumber, FillChar);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_CheckAsCompletion(IntPtr Client, ref Int32 opResult);
+ public bool CheckAsCompletion(ref int opResult)
+ {
+ return Cli_CheckAsCompletion(Client, ref opResult) == JobComplete;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_WaitAsCompletion(IntPtr Client, Int32 Timeout);
+ public int WaitAsCompletion(int Timeout)
+ {
+ return Cli_WaitAsCompletion(Client, Timeout);
+ }
+
+ #endregion
+
+ #region [Info Functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetExecTime(IntPtr Client, ref UInt32 Time);
+ public int ExecTime()
+ {
+ UInt32 Time = new UInt32();
+ if (Cli_GetExecTime(Client, ref Time) == 0)
+ return (int)(Time);
+ else
+ return -1;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetLastError(IntPtr Client, ref Int32 LastError);
+ public int LastError()
+ {
+ Int32 ClientLastError = new Int32();
+ if (Cli_GetLastError(Client, ref ClientLastError) == 0)
+ return (int)ClientLastError;
+ else
+ return -1;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetPduLength(IntPtr Client, ref Int32 Requested, ref Int32 Negotiated);
+
+ public int RequestedPduLength()
+ {
+ Int32 Requested = new Int32();
+ Int32 Negotiated = new Int32();
+ if (Cli_GetPduLength(Client, ref Requested, ref Negotiated) == 0)
+ return Requested;
+ else
+ return -1;
+ }
+
+ public int NegotiatedPduLength()
+ {
+ Int32 Requested = new Int32();
+ Int32 Negotiated = new Int32();
+ if (Cli_GetPduLength(Client, ref Requested, ref Negotiated) == 0)
+ return Negotiated;
+ else
+ return -1;
+ }
+
+ [DllImport(S7Consts.Snap7LibName, CharSet = CharSet.Ansi)]
+ protected static extern int Cli_ErrorText(int Error, StringBuilder ErrMsg, int TextSize);
+ public string ErrorText(int Error)
+ {
+ StringBuilder Message = new StringBuilder(MsgTextLen);
+ Cli_ErrorText(Error, Message, MsgTextLen);
+ return Message.ToString();
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Cli_GetConnected(IntPtr Client, ref UInt32 IsConnected);
+ public bool Connected()
+ {
+ UInt32 IsConnected = new UInt32();
+ if (Cli_GetConnected(Client, ref IsConnected) == 0)
+ return IsConnected!=0;
+ else
+ return false;
+ }
+
+ #endregion
+ }
+
+ public class S7Server
+ {
+ #region [Constants, private vars and TypeDefs]
+
+ private const int MsgTextLen = 1024;
+ private const int mkEvent = 0;
+ private const int mkLog = 1;
+
+ // Server Area ID (use with Register/unregister - Lock/unlock Area)
+ public static readonly int srvAreaPE = 0;
+ public static readonly int srvAreaPA = 1;
+ public static readonly int srvAreaMK = 2;
+ public static readonly int srvAreaCT = 3;
+ public static readonly int srvAreaTM = 4;
+ public static readonly int srvAreaDB = 5;
+ // Errors
+ public static readonly uint errSrvCannotStart = 0x00100000; // Server cannot start
+ public static readonly uint errSrvDBNullPointer = 0x00200000; // Passed null as PData
+ public static readonly uint errSrvAreaAlreadyExists = 0x00300000; // Area Re-registration
+ public static readonly uint errSrvUnknownArea = 0x00400000; // Unknown area
+ public static readonly uint errSrvInvalidParams = 0x00500000; // Invalid param(s) supplied
+ public static readonly uint errSrvTooManyDB = 0x00600000; // Cannot register DB
+ public static readonly uint errSrvInvalidParamNumber = 0x00700000; // Invalid param (srv_get/set_param)
+ public static readonly uint errSrvCannotChangeParam = 0x00800000; // Cannot change because running
+
+ // TCP Server Event codes
+ public static readonly uint evcServerStarted = 0x00000001;
+ public static readonly uint evcServerStopped = 0x00000002;
+ public static readonly uint evcListenerCannotStart = 0x00000004;
+ public static readonly uint evcClientAdded = 0x00000008;
+ public static readonly uint evcClientRejected = 0x00000010;
+ public static readonly uint evcClientNoRoom = 0x00000020;
+ public static readonly uint evcClientException = 0x00000040;
+ public static readonly uint evcClientDisconnected = 0x00000080;
+ public static readonly uint evcClientTerminated = 0x00000100;
+ public static readonly uint evcClientsDropped = 0x00000200;
+ public static readonly uint evcReserved_00000400 = 0x00000400; // actually unused
+ public static readonly uint evcReserved_00000800 = 0x00000800; // actually unused
+ public static readonly uint evcReserved_00001000 = 0x00001000; // actually unused
+ public static readonly uint evcReserved_00002000 = 0x00002000; // actually unused
+ public static readonly uint evcReserved_00004000 = 0x00004000; // actually unused
+ public static readonly uint evcReserved_00008000 = 0x00008000; // actually unused
+ // S7 Server Event Code
+ public static readonly uint evcPDUincoming = 0x00010000;
+ public static readonly uint evcDataRead = 0x00020000;
+ public static readonly uint evcDataWrite = 0x00040000;
+ public static readonly uint evcNegotiatePDU = 0x00080000;
+ public static readonly uint evcReadSZL = 0x00100000;
+ public static readonly uint evcClock = 0x00200000;
+ public static readonly uint evcUpload = 0x00400000;
+ public static readonly uint evcDownload = 0x00800000;
+ public static readonly uint evcDirectory = 0x01000000;
+ public static readonly uint evcSecurity = 0x02000000;
+ public static readonly uint evcControl = 0x04000000;
+ public static readonly uint evcReserved_08000000 = 0x08000000; // actually unused
+ public static readonly uint evcReserved_10000000 = 0x10000000; // actually unused
+ public static readonly uint evcReserved_20000000 = 0x20000000; // actually unused
+ public static readonly uint evcReserved_40000000 = 0x40000000; // actually unused
+ public static readonly uint evcReserved_80000000 = 0x80000000; // actually unused
+ // Masks to enable/disable all events
+ public static readonly uint evcAll = 0xFFFFFFFF;
+ public static readonly uint evcNone = 0x00000000;
+ // Event SubCodes
+ public static readonly ushort evsUnknown = 0x0000;
+ public static readonly ushort evsStartUpload = 0x0001;
+ public static readonly ushort evsStartDownload = 0x0001;
+ public static readonly ushort evsGetBlockList = 0x0001;
+ public static readonly ushort evsStartListBoT = 0x0002;
+ public static readonly ushort evsListBoT = 0x0003;
+ public static readonly ushort evsGetBlockInfo = 0x0004;
+ public static readonly ushort evsGetClock = 0x0001;
+ public static readonly ushort evsSetClock = 0x0002;
+ public static readonly ushort evsSetPassword = 0x0001;
+ public static readonly ushort evsClrPassword = 0x0002;
+ // Event Params : functions group
+ public static readonly ushort grProgrammer = 0x0041;
+ public static readonly ushort grCyclicData = 0x0042;
+ public static readonly ushort grBlocksInfo = 0x0043;
+ public static readonly ushort grSZL = 0x0044;
+ public static readonly ushort grPassword = 0x0045;
+ public static readonly ushort grBSend = 0x0046;
+ public static readonly ushort grClock = 0x0047;
+ public static readonly ushort grSecurity = 0x0045;
+ // Event Params : control codes
+ public static readonly ushort CodeControlUnknown = 0x0000;
+ public static readonly ushort CodeControlColdStart = 0x0001;
+ public static readonly ushort CodeControlWarmStart = 0x0002;
+ public static readonly ushort CodeControlStop = 0x0003;
+ public static readonly ushort CodeControlCompress = 0x0004;
+ public static readonly ushort CodeControlCpyRamRom = 0x0005;
+ public static readonly ushort CodeControlInsDel = 0x0006;
+ // Event Result
+ public static readonly ushort evrNoError = 0x0000;
+ public static readonly ushort evrFragmentRejected = 0x0001;
+ public static readonly ushort evrMalformedPDU = 0x0002;
+ public static readonly ushort evrSparseBytes = 0x0003;
+ public static readonly ushort evrCannotHandlePDU = 0x0004;
+ public static readonly ushort evrNotImplemented = 0x0005;
+ public static readonly ushort evrErrException = 0x0006;
+ public static readonly ushort evrErrAreaNotFound = 0x0007;
+ public static readonly ushort evrErrOutOfRange = 0x0008;
+ public static readonly ushort evrErrOverPDU = 0x0009;
+ public static readonly ushort evrErrTransportSize = 0x000A;
+ public static readonly ushort evrInvalidGroupUData = 0x000B;
+ public static readonly ushort evrInvalidSZL = 0x000C;
+ public static readonly ushort evrDataSizeMismatch = 0x000D;
+ public static readonly ushort evrCannotUpload = 0x000E;
+ public static readonly ushort evrCannotDownload = 0x000F;
+ public static readonly ushort evrUploadInvalidID = 0x0010;
+ public static readonly ushort evrResNotFound = 0x0011;
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct USrvEvent
+ {
+ public IntPtr EvtTime; // It's platform dependent (32 or 64 bit)
+ public Int32 EvtSender;
+ public UInt32 EvtCode;
+ public ushort EvtRetCode;
+ public ushort EvtParam1;
+ public ushort EvtParam2;
+ public ushort EvtParam3;
+ public ushort EvtParam4;
+ }
+
+ public struct SrvEvent
+ {
+ public DateTime EvtTime;
+ public Int32 EvtSender;
+ public UInt32 EvtCode;
+ public ushort EvtRetCode;
+ public ushort EvtParam1;
+ public ushort EvtParam2;
+ public ushort EvtParam3;
+ public ushort EvtParam4;
+ }
+
+ private IntPtr Server;
+
+ #endregion
+
+ #region [Class Control]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern IntPtr Srv_Create();
+ public S7Server()
+ {
+ Server = Srv_Create();
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_Destroy(ref IntPtr Server);
+ ~S7Server()
+ {
+ Srv_Destroy(ref Server);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_StartTo(IntPtr Server, [MarshalAs(UnmanagedType.LPStr)] string Address);
+ public int StartTo(string Address)
+ {
+ return Srv_StartTo(Server, Address);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_Start(IntPtr Server);
+ public int Start()
+ {
+ return Srv_Start(Server);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_Stop(IntPtr Server);
+ public int Stop()
+ {
+ return Srv_Stop(Server);
+ }
+
+ // Get/SetParam needs a void* parameter, internally it decides the kind of pointer
+ // in accord to ParamNumber.
+ // To avoid the use of unsafe code we split the DLL functions and use overloaded methods.
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_GetParam")]
+ protected static extern int Srv_GetParam_i16(IntPtr Server, Int32 ParamNumber, ref Int16 IntValue);
+ public int GetParam(Int32 ParamNumber, ref Int16 IntValue)
+ {
+ return Srv_GetParam_i16(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_GetParam")]
+ protected static extern int Srv_GetParam_u16(IntPtr Server, Int32 ParamNumber, ref UInt16 IntValue);
+ public int GetParam(Int32 ParamNumber, ref UInt16 IntValue)
+ {
+ return Srv_GetParam_u16(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_GetParam")]
+ protected static extern int Srv_GetParam_i32(IntPtr Server, Int32 ParamNumber, ref Int32 IntValue);
+ public int GetParam(Int32 ParamNumber, ref Int32 IntValue)
+ {
+ return Srv_GetParam_i32(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_GetParam")]
+ protected static extern int Srv_GetParam_u32(IntPtr Server, Int32 ParamNumber, ref UInt32 IntValue);
+ public int GetParam(Int32 ParamNumber, ref UInt32 IntValue)
+ {
+ return Srv_GetParam_u32(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_GetParam")]
+ protected static extern int Srv_GetParam_i64(IntPtr Server, Int32 ParamNumber, ref Int64 IntValue);
+ public int GetParam(Int32 ParamNumber, ref Int64 IntValue)
+ {
+ return Srv_GetParam_i64(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_GetParam")]
+ protected static extern int Srv_GetParam_u64(IntPtr Server, Int32 ParamNumber, ref UInt64 IntValue);
+ public int GetParam(Int32 ParamNumber, ref UInt64 IntValue)
+ {
+ return Srv_GetParam_u64(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_SetParam")]
+ protected static extern int Srv_SetParam_i16(IntPtr Server, Int32 ParamNumber, ref Int16 IntValue);
+ public int SetParam(Int32 ParamNumber, ref Int16 IntValue)
+ {
+ return Srv_SetParam_i16(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_SetParam")]
+ protected static extern int Srv_SetParam_u16(IntPtr Server, Int32 ParamNumber, ref UInt16 IntValue);
+ public int SetParam(Int32 ParamNumber, ref UInt16 IntValue)
+ {
+ return Srv_SetParam_u16(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_SetParam")]
+ protected static extern int Srv_SetParam_i32(IntPtr Server, Int32 ParamNumber, ref Int32 IntValue);
+ public int SetParam(Int32 ParamNumber, ref Int32 IntValue)
+ {
+ return Srv_SetParam_i32(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_SetParam")]
+ protected static extern int Srv_SetParam_u32(IntPtr Server, Int32 ParamNumber, ref UInt32 IntValue);
+ public int SetParam(Int32 ParamNumber, ref UInt32 IntValue)
+ {
+ return Srv_SetParam_u32(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_SetParam")]
+ protected static extern int Srv_SetParam_i64(IntPtr Server, Int32 ParamNumber, ref Int64 IntValue);
+ public int SetParam(Int32 ParamNumber, ref Int64 IntValue)
+ {
+ return Srv_SetParam_i64(Server, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Srv_SetParam")]
+ protected static extern int Srv_SetParam_u64(IntPtr Server, Int32 ParamNumber, ref UInt64 IntValue);
+ public int SetParam(Int32 ParamNumber, ref UInt64 IntValue)
+ {
+ return Srv_SetParam_u64(Server, ParamNumber, ref IntValue);
+ }
+
+ #endregion
+
+ #region [Data Areas functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_RegisterArea(IntPtr Server, Int32 AreaCode, Int32 Index, byte[] pUsrData, Int32 Size);
+ public int RegisterArea(Int32 AreaCode, Int32 Index, byte[] pUsrData, Int32 Size)
+ {
+ return Srv_RegisterArea(Server, AreaCode, Index, pUsrData, Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_UnregisterArea(IntPtr Server, Int32 AreaCode, Int32 Index);
+ public int UnregisterArea(Int32 AreaCode, Int32 Index)
+ {
+ return Srv_UnregisterArea(Server, AreaCode, Index);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_LockArea(IntPtr Server, Int32 AreaCode, Int32 Index);
+ public int LockArea(Int32 AreaCode, Int32 Index)
+ {
+ return Srv_LockArea(Server, AreaCode, Index);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_UnlockArea(IntPtr Server, Int32 AreaCode, Int32 Index);
+ public int UnlockArea(Int32 AreaCode, Int32 Index)
+ {
+ return Srv_UnlockArea(Server, AreaCode, Index);
+ }
+
+ #endregion
+
+ #region [Notification functions (Events)]
+
+ public delegate void TSrvCallback(IntPtr usrPtr, ref USrvEvent Event, int Size);
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_SetEventsCallback(IntPtr Server, TSrvCallback Callback, IntPtr usrPtr);
+ public int SetEventsCallBack(TSrvCallback Callback, IntPtr usrPtr)
+ {
+ return Srv_SetEventsCallback(Server, Callback, usrPtr);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_SetReadEventsCallback(IntPtr Server, TSrvCallback Callback, IntPtr usrPtr);
+ public int SetReadEventsCallBack(TSrvCallback Callback, IntPtr usrPtr)
+ {
+ return Srv_SetReadEventsCallback(Server, Callback, usrPtr);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_PickEvent(IntPtr Server, ref USrvEvent Event, ref Int32 EvtReady);
+ public bool PickEvent(ref USrvEvent Event)
+ {
+ Int32 EvtReady = new Int32();
+ if (Srv_PickEvent(Server, ref Event, ref EvtReady) == 0)
+ return EvtReady != 0;
+ else
+ return false;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_ClearEvents(IntPtr Server);
+ public int ClearEvents()
+ {
+ return Srv_ClearEvents(Server);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, CharSet = CharSet.Ansi)]
+ protected static extern int Srv_EventText(ref USrvEvent Event, StringBuilder EvtMsg, int TextSize);
+ public string EventText(ref USrvEvent Event)
+ {
+ StringBuilder Message = new StringBuilder(MsgTextLen);
+ Srv_EventText(ref Event, Message, MsgTextLen);
+ return Message.ToString();
+ }
+
+ public DateTime EvtTimeToDateTime(IntPtr TimeStamp)
+ {
+ DateTime UnixStartEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
+ return UnixStartEpoch.AddSeconds(Convert.ToDouble(TimeStamp));
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_GetMask(IntPtr Server, Int32 MaskKind, ref UInt32 Mask);
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_SetMask(IntPtr Server, Int32 MaskKind, UInt32 Mask);
+
+ // Property LogMask R/W
+ public UInt32 LogMask {
+ get
+ {
+ UInt32 Mask = new UInt32();
+ if (Srv_GetMask(Server, S7Server.mkLog, ref Mask)==0)
+ return Mask;
+ else
+ return 0;
+ }
+ set
+ {
+ Srv_SetMask(Server, S7Server.mkLog, value);
+ }
+ }
+
+ // Property EventMask R/W
+ public UInt32 EventMask
+ {
+ get
+ {
+ UInt32 Mask = new UInt32();
+ if (Srv_GetMask(Server, S7Server.mkEvent, ref Mask) == 0)
+ return Mask;
+ else
+ return 0;
+ }
+ set
+ {
+ Srv_SetMask(Server, S7Server.mkEvent, value);
+ }
+ }
+
+
+ #endregion
+
+ #region [Info functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_GetStatus(IntPtr Server, ref Int32 ServerStatus, ref Int32 CpuStatus, ref Int32 ClientsCount);
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Srv_SetCpuStatus(IntPtr Server, Int32 CpuStatus);
+
+ // Property Virtual CPU status R/W
+ public int CpuStatus
+ {
+ get
+ {
+ Int32 CStatus = new Int32();
+ Int32 SStatus = new Int32();
+ Int32 CCount = new Int32();
+
+ if (Srv_GetStatus(Server, ref CStatus, ref SStatus, ref CCount) == 0)
+ return CStatus;
+ else
+ return -1;
+ }
+ set
+ {
+ Srv_SetCpuStatus(Server, value);
+ }
+ }
+
+ // Property Server Status Read Only
+ public int ServerStatus
+ {
+ get
+ {
+ Int32 CStatus = new Int32();
+ Int32 SStatus = new Int32();
+ Int32 CCount = new Int32();
+ if (Srv_GetStatus(Server, ref CStatus, ref SStatus, ref CCount) == 0)
+ return SStatus;
+ else
+ return -1;
+ }
+ }
+
+ // Property Clients Count Read Only
+ public int ClientsCount
+ {
+ get
+ {
+ Int32 CStatus = new Int32();
+ Int32 SStatus = new Int32();
+ Int32 CCount = new Int32();
+ if (Srv_GetStatus(Server, ref CStatus, ref SStatus, ref CCount) == 0)
+ return CCount;
+ else
+ return -1;
+ }
+ }
+
+ [DllImport(S7Consts.Snap7LibName, CharSet = CharSet.Ansi)]
+ protected static extern int Srv_ErrorText(int Error, StringBuilder ErrMsg, int TextSize);
+ public string ErrorText(int Error)
+ {
+ StringBuilder Message = new StringBuilder(MsgTextLen);
+ Srv_ErrorText(Error, Message, MsgTextLen);
+ return Message.ToString();
+ }
+
+ #endregion
+ }
+
+ public class S7Partner
+ {
+ #region [Constants, private vars and TypeDefs]
+
+ private const int MsgTextLen = 1024;
+
+ // Status
+ public static readonly int par_stopped = 0; // stopped
+ public static readonly int par_connecting = 1; // running and active connecting
+ public static readonly int par_waiting = 2; // running and waiting for a connection
+ public static readonly int par_linked = 3; // running and connected : linked
+ public static readonly int par_sending = 4; // sending data
+ public static readonly int par_receiving = 5; // receiving data
+ public static readonly int par_binderror = 6; // error starting passive server
+
+ // Errors
+ public static readonly uint errParAddressInUse = 0x00200000;
+ public static readonly uint errParNoRoom = 0x00300000;
+ public static readonly uint errServerNoRoom = 0x00400000;
+ public static readonly uint errParInvalidParams = 0x00500000;
+ public static readonly uint errParNotLinked = 0x00600000;
+ public static readonly uint errParBusy = 0x00700000;
+ public static readonly uint errParFrameTimeout = 0x00800000;
+ public static readonly uint errParInvalidPDU = 0x00900000;
+ public static readonly uint errParSendTimeout = 0x00A00000;
+ public static readonly uint errParRecvTimeout = 0x00B00000;
+ public static readonly uint errParSendRefused = 0x00C00000;
+ public static readonly uint errParNegotiatingPDU = 0x00D00000;
+ public static readonly uint errParSendingBlock = 0x00E00000;
+ public static readonly uint errParRecvingBlock = 0x00F00000;
+ public static readonly uint errBindError = 0x01000000;
+ public static readonly uint errParDestroying = 0x01100000;
+ public static readonly uint errParInvalidParamNumber = 0x01200000;
+ public static readonly uint errParCannotChangeParam = 0x01300000;
+
+ // Generic byte buffer structure, you may need to declare a more
+ // specialistic one in your program.
+ // It's used to cast the input pointer that cames from the callback.
+ // See the passive partned demo and the delegate S7ParRecvCallback.
+
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ public struct S7Buffer
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x8000)]
+ public byte[] Data;
+ }
+
+ // Job status
+ private const int JobComplete = 0;
+ private const int JobPending = 1;
+
+ private IntPtr Partner;
+
+ private Int32 parBytesSent;
+ private Int32 parBytesRecv;
+ private Int32 parSendErrors;
+ private Int32 parRecvErrors;
+
+ #endregion
+
+ #region [Class Control]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern IntPtr Par_Create(Int32 ParActive);
+ public S7Partner(int Active)
+ {
+ Partner= Par_Create(Active);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_Destroy(ref IntPtr Partner);
+ ~S7Partner()
+ {
+ Par_Destroy(ref Partner);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_StartTo(
+ IntPtr Partner,
+ [MarshalAs(UnmanagedType.LPStr)] string LocalAddress,
+ [MarshalAs(UnmanagedType.LPStr)] string RemoteAddress,
+ UInt16 LocalTSAP,
+ UInt16 RemoteTSAP);
+
+ public int StartTo(
+ string LocalAddress,
+ string RemoteAddress,
+ UInt16 LocalTSAP,
+ UInt16 RemoteTSAP)
+ {
+ return Par_StartTo(Partner, LocalAddress, RemoteAddress, LocalTSAP, RemoteTSAP);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_Start(IntPtr Partner);
+ public int Start()
+ {
+ return Par_Start(Partner);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_Stop(IntPtr Partner);
+ public int Stop()
+ {
+ return Par_Stop(Partner);
+ }
+
+ // Get/SetParam needs a void* parameter, internally it decides the kind of pointer
+ // in accord to ParamNumber.
+ // To avoid the use of unsafe code we split the DLL functions and use overloaded methods.
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_GetParam")]
+ protected static extern int Par_GetParam_i16(IntPtr Partner, Int32 ParamNumber, ref Int16 IntValue);
+ public int GetParam(Int32 ParamNumber, ref Int16 IntValue)
+ {
+ return Par_GetParam_i16(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_GetParam")]
+ protected static extern int Par_GetParam_u16(IntPtr Partner, Int32 ParamNumber, ref UInt16 IntValue);
+ public int GetParam(Int32 ParamNumber, ref UInt16 IntValue)
+ {
+ return Par_GetParam_u16(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_GetParam")]
+ protected static extern int Par_GetParam_i32(IntPtr Partner, Int32 ParamNumber, ref Int32 IntValue);
+ public int GetParam(Int32 ParamNumber, ref Int32 IntValue)
+ {
+ return Par_GetParam_i32(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_GetParam")]
+ protected static extern int Par_GetParam_u32(IntPtr Partner, Int32 ParamNumber, ref UInt32 IntValue);
+ public int GetParam(Int32 ParamNumber, ref UInt32 IntValue)
+ {
+ return Par_GetParam_u32(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_GetParam")]
+ protected static extern int Par_GetParam_i64(IntPtr Partner, Int32 ParamNumber, ref Int64 IntValue);
+ public int GetParam(Int32 ParamNumber, ref Int64 IntValue)
+ {
+ return Par_GetParam_i64(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_GetParam")]
+ protected static extern int Par_GetParam_u64(IntPtr Partner, Int32 ParamNumber, ref UInt64 IntValue);
+ public int GetParam(Int32 ParamNumber, ref UInt64 IntValue)
+ {
+ return Par_GetParam_u64(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_SetParam")]
+ protected static extern int Par_SetParam_i16(IntPtr Partner, Int32 ParamNumber, ref Int16 IntValue);
+ public int SetParam(Int32 ParamNumber, ref Int16 IntValue)
+ {
+ return Par_SetParam_i16(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_SetParam")]
+ protected static extern int Par_SetParam_u16(IntPtr Partner, Int32 ParamNumber, ref UInt16 IntValue);
+ public int SetParam(Int32 ParamNumber, ref UInt16 IntValue)
+ {
+ return Par_SetParam_u16(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_SetParam")]
+ protected static extern int Par_SetParam_i32(IntPtr Partner, Int32 ParamNumber, ref Int32 IntValue);
+ public int SetParam(Int32 ParamNumber, ref Int32 IntValue)
+ {
+ return Par_SetParam_i32(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_SetParam")]
+ protected static extern int Par_SetParam_u32(IntPtr Partner, Int32 ParamNumber, ref UInt32 IntValue);
+ public int SetParam(Int32 ParamNumber, ref UInt32 IntValue)
+ {
+ return Par_SetParam_u32(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_SetParam")]
+ protected static extern int Par_SetParam_i64(IntPtr Partner, Int32 ParamNumber, ref Int64 IntValue);
+ public int SetParam(Int32 ParamNumber, ref Int64 IntValue)
+ {
+ return Par_SetParam_i64(Partner, ParamNumber, ref IntValue);
+ }
+
+ [DllImport(S7Consts.Snap7LibName, EntryPoint = "Par_SetParam")]
+ protected static extern int Par_SetParam_u64(IntPtr Partner, Int32 ParamNumber, ref UInt64 IntValue);
+ public int SetParam(Int32 ParamNumber, ref UInt64 IntValue)
+ {
+ return Par_SetParam_u64(Partner, ParamNumber, ref IntValue);
+ }
+
+ #endregion
+
+ #region [Data I/O functions : BSend]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_BSend(IntPtr Partner, UInt32 R_ID, byte[] Buffer, Int32 Size);
+ public int BSend(UInt32 R_ID, byte[] Buffer, Int32 Size)
+ {
+ return Par_BSend(Partner, R_ID, Buffer, Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_AsBSend(IntPtr Partner, UInt32 R_ID, byte[] Buffer, Int32 Size);
+ public int AsBSend(UInt32 R_ID, byte[] Buffer, Int32 Size)
+ {
+ return Par_AsBSend(Partner, R_ID, Buffer, Size);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_CheckAsBSendCompletion(IntPtr Partner, ref Int32 opResult);
+ public bool CheckAsBSendCompletion(ref int opResult)
+ {
+ return Par_CheckAsBSendCompletion(Partner, ref opResult)==JobComplete;
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_WaitAsBSendCompletion(IntPtr Partner, Int32 Timeout);
+ public int WaitAsBSendCompletion(int Timeout)
+ {
+ return Par_WaitAsBSendCompletion(Partner, Timeout);
+ }
+
+ public delegate void S7ParSendCompletion(IntPtr usrPtr, int opResult);
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_SetSendCallback(IntPtr Partner, S7ParSendCompletion Completion, IntPtr usrPtr);
+ public int SetSendCallBack(S7ParSendCompletion Completion, IntPtr usrPtr)
+ {
+ return Par_SetSendCallback(Partner, Completion, usrPtr);
+ }
+
+ #endregion
+
+ #region [Data I/O functions : BRecv]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_BRecv(IntPtr Partner, ref UInt32 R_ID, byte[] Buffer, ref Int32 Size, UInt32 Timeout);
+ public int BRecv(ref UInt32 R_ID, byte[] Buffer, ref Int32 Size, UInt32 Timeout)
+ {
+ return Par_BRecv(Partner, ref R_ID, Buffer, ref Size, Timeout);
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_CheckAsBRecvCompletion(IntPtr Partner, ref Int32 opResult, ref UInt32 R_ID, byte[] Buffer, ref Int32 Size);
+ public bool CheckAsBRecvCompletion(ref Int32 opResult, ref UInt32 R_ID, byte[] Buffer, ref Int32 Size)
+ {
+ Par_CheckAsBRecvCompletion(Partner, ref opResult, ref R_ID, Buffer, ref Size);
+ return opResult == JobComplete;
+ }
+
+ public delegate void S7ParRecvCallback(IntPtr usrPtr, int opResult, uint R_ID, IntPtr pData, int Size);
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_SetRecvCallback(IntPtr Partner, S7ParRecvCallback Callback, IntPtr usrPtr);
+ public int SetRecvCallback(S7ParRecvCallback Callback, IntPtr usrPtr)
+ {
+ return Par_SetRecvCallback(Partner, Callback, usrPtr);
+ }
+
+ #endregion
+
+ #region [Info functions]
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_GetLastError(IntPtr Partner, ref Int32 LastError);
+ public int LastError(ref Int32 LastError)
+ {
+ Int32 PartnerLastError = new Int32();
+ if (Par_GetLastError(Partner, ref PartnerLastError) == 0)
+ return (int)PartnerLastError;
+ else
+ return -1;
+ }
+
+ [DllImport(S7Consts.Snap7LibName, CharSet = CharSet.Ansi)]
+ protected static extern int Par_ErrorText(int Error, StringBuilder ErrMsg, int TextSize);
+ public string ErrorText(int Error)
+ {
+ StringBuilder Message = new StringBuilder(MsgTextLen);
+ Par_ErrorText(Error, Message, MsgTextLen);
+ return Message.ToString();
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_GetStats(IntPtr Partner, ref Int32 BytesSent, ref Int32 BytesRecv,
+ ref Int32 SendErrors, ref Int32 RecvErrors);
+
+ private void GetStatistics()
+ {
+ if (Par_GetStats(Partner, ref parBytesSent, ref parBytesRecv, ref parSendErrors, ref parRecvErrors) != 0)
+ {
+ parBytesSent = -1;
+ parBytesRecv = -1;
+ parSendErrors = -1;
+ parRecvErrors = -1;
+ }
+ }
+
+ public int BytesSent
+ {
+ get
+ {
+ GetStatistics();
+ return parBytesSent;
+ }
+ }
+
+ public int BytesRecv
+ {
+ get
+ {
+ GetStatistics();
+ return parBytesRecv;
+ }
+ }
+
+ public int SendErrors
+ {
+ get
+ {
+ GetStatistics();
+ return parSendErrors;
+ }
+ }
+
+ public int RecvErrors
+ {
+ get
+ {
+ GetStatistics();
+ return parRecvErrors;
+ }
+ }
+
+ [DllImport(S7Consts.Snap7LibName)]
+ protected static extern int Par_GetStatus(IntPtr Partner, ref Int32 Status);
+
+ public int Status
+ {
+ get
+ {
+ int ParStatus = new int();
+ if (Par_GetStatus(Partner, ref ParStatus) != 0)
+ return -1;
+ else
+ return ParStatus;
+ }
+ }
+ // simply useful
+ public bool Linked
+ {
+ get
+ {
+ return Status == par_linked;
+ }
+ }
+ #endregion
+
+ }
+}
diff --git a/S7.Net.UnitTest/snap7.dll b/S7.Net.UnitTest/snap7.dll
new file mode 100644
index 0000000..d52c361
Binary files /dev/null and b/S7.Net.UnitTest/snap7.dll differ
diff --git a/S7.sln b/S7.sln
index 0cd6962..d1dc768 100644
--- a/S7.sln
+++ b/S7.sln
@@ -8,6 +8,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S7.Net.UnitTest", "S7.Net.UnitTest\S7.Net.UnitTest.csproj", "{303CCED6-9ABC-4899-A509-743341AAA804}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -18,6 +20,10 @@ Global
{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
+ {303CCED6-9ABC-4899-A509-743341AAA804}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {303CCED6-9ABC-4899-A509-743341AAA804}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {303CCED6-9ABC-4899-A509-743341AAA804}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {303CCED6-9ABC-4899-A509-743341AAA804}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE