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