From 4dc0f9c9876074e6498c3f39a7ff9e33f1bb4000 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Wed, 5 Dec 2018 06:43:10 +0100 Subject: [PATCH] - .NET API: Added support for IedConnection.GetState and StateChangedHandler --- dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs | 119 ++++++++++++++++-- dotnet/client_example_async/Program.cs | 6 + 2 files changed, 114 insertions(+), 11 deletions(-) diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs index 4ba47ea9..68a22ff3 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs @@ -320,7 +320,7 @@ namespace IEC61850 /// This class acts as the entry point for the IEC 61850 client API. It represents a single /// (MMS) connection to a server. /// - public partial class IedConnection + public partial class IedConnection : IDisposable { /************* * MmsValue @@ -408,6 +408,9 @@ namespace IEC61850 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void InternalConnectionClosedHandler (IntPtr parameter,IntPtr Iedconnection); + /// + /// Called when the connection is closed + /// public delegate void ConnectionClosedHandler (IedConnection connection); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] @@ -463,6 +466,20 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void IedConnection_uninstallReportHandler(IntPtr connection, string rcbReference); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int IedConnection_getState(IntPtr connection); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate void InternalStateChangedHandler (IntPtr parameter,IntPtr iedConnection, int newState); + + /// + /// Called when there is a change in the connection state + /// + public delegate void StateChangedHandler (IedConnection connection, IedConnectionState newState); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void IedConnection_installStateChangedHandler(IntPtr connection, InternalStateChangedHandler handler, IntPtr parameter); + /********************* * Async functions *********************/ @@ -543,8 +560,11 @@ namespace IEC61850 static extern void LinkedList_add (IntPtr self, IntPtr data); private IntPtr connection = IntPtr.Zero; - private InternalConnectionClosedHandler connectionClosedHandler; - private ConnectionClosedHandler userProvidedHandler = null; + private InternalConnectionClosedHandler connectionClosedHandler = null; + private ConnectionClosedHandler userProvidedConnectionClosedHandler = null; + + private InternalStateChangedHandler internalStateChangedHandler = null; + private StateChangedHandler stateChangedHandler = null; /// /// Initializes a new instance of the class. @@ -641,7 +661,10 @@ namespace IEC61850 } } - + /// + /// Gets the underlying MmsConnection instance. + /// + /// The mms connection. public MmsConnection GetMmsConnection () { IntPtr mmsConnectionPtr = IedConnection_getMmsConnection(connection); @@ -663,6 +686,15 @@ namespace IEC61850 throw new IedConnectionException ("Connect to " + hostname + ":" + tcpPort + " failed", error); } + /// + /// Gets the current state of the connection + /// + /// The current connection state + public IedConnectionState GetState() + { + return (IedConnectionState)IedConnection_getState(connection); + } + /// Establish an MMS connection to a server. /// This exception is thrown if there is a connection or service error. public void Connect (string hostname) @@ -1373,8 +1405,8 @@ namespace IEC61850 private void MyConnectionClosedHandler (IntPtr parameter, IntPtr self) { - if (userProvidedHandler != null) - userProvidedHandler (this); + if (userProvidedConnectionClosedHandler != null) + userProvidedConnectionClosedHandler (this); } /// @@ -1385,15 +1417,51 @@ namespace IEC61850 /// by a prior function call. /// The user provided callback handler /// This exception is thrown if there is a connection or service error - public void InstallConnectionClosedHandler (ConnectionClosedHandler handler) + [Obsolete("ConnectionClosedHandler is deprecated, please use ConnectionEventHandler instead")] + public void InstallConnectionClosedHandler (ConnectionClosedHandler handler) { - connectionClosedHandler = new InternalConnectionClosedHandler (MyConnectionClosedHandler); - - userProvidedHandler = handler; + if (connectionClosedHandler == null) + { + connectionClosedHandler = new InternalConnectionClosedHandler(MyConnectionClosedHandler); + IedConnection_installConnectionClosedHandler (connection, connectionClosedHandler, connection); + } - IedConnection_installConnectionClosedHandler (connection, connectionClosedHandler, connection); + userProvidedConnectionClosedHandler = handler; } + private void MyStateChangedHandler(IntPtr parameter, IntPtr IedConnection, int newState) + { + if (stateChangedHandler != null) + stateChangedHandler(this, (IedConnectionState)newState); + } + + /// + /// Sets the handler for StateChanged events + /// + /// The state changed event handler + public void InstallStateChangedHandler (StateChangedHandler handler) + { + stateChangedHandler = handler; + + if (internalStateChangedHandler == null) + { + internalStateChangedHandler = new InternalStateChangedHandler(MyStateChangedHandler); + IedConnection_installStateChangedHandler(connection, internalStateChangedHandler, IntPtr.Zero); + } + } + + /// + /// Sets the handler for StateChanged events + /// + /// The state changed event handler + public StateChangedHandler StateChanged + { + set + { + InstallStateChangedHandler(value); + } + } + /// /// Read the values of a data set (GetDataSetValues service). /// @@ -1979,6 +2047,35 @@ namespace IEC61850 } } + /// + /// Connection state of an IedConnection instance + /// + public enum IedConnectionState + { + /// + /// The connection is closed. Requests cannot be sent. + /// + IED_STATE_CLOSED = 0, + + /// + /// The connection is connecting. Requests cannot be sent yet. + /// + IED_STATE_CONNECTING = 1, + + /// + /// The connection is up. Requests can be sent. + /// + IED_STATE_CONNECTED = 2, + + /// + /// The connection is closing. Requests connect be sent. + /// + IED_STATE_CLOSING = 3 + } + + /// + /// Error codes for client side functions + /// public enum IedClientError { /* general errors */ diff --git a/dotnet/client_example_async/Program.cs b/dotnet/client_example_async/Program.cs index 22b2eb44..08034f89 100644 --- a/dotnet/client_example_async/Program.cs +++ b/dotnet/client_example_async/Program.cs @@ -31,6 +31,10 @@ namespace client_example_async { con.MaxPduSize = 1000; + con.StateChanged = delegate(IedConnection connection, IedConnectionState newState) { + Console.WriteLine("state change: " + newState.ToString()); + }; + con.Connect(hostname, port); AutoResetEvent waitForCallback = new AutoResetEvent(false); @@ -161,6 +165,8 @@ namespace client_example_async Thread.Sleep(5000); con.Abort(); + + Console.WriteLine("Aborted"); } catch (IedConnectionException e) {