diff --git a/dotnet/IEC61850forCSharp/Control.cs b/dotnet/IEC61850forCSharp/Control.cs
index 4fa909cf..c096c923 100644
--- a/dotnet/IEC61850forCSharp/Control.cs
+++ b/dotnet/IEC61850forCSharp/Control.cs
@@ -28,10 +28,7 @@ using IEC61850.Common;
namespace IEC61850
{
-
- ///
- /// IEC 61850 common API parts (used by client and server API)
- ///
+ // IEC 61850 common API parts (used by client and server API)
namespace Common {
///
@@ -76,8 +73,8 @@ namespace IEC61850
}
}
- namespace Client {
-
+ namespace Client
+ {
[StructLayout(LayoutKind.Sequential)]
internal struct LastApplErrorInternal
{
@@ -128,7 +125,10 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern int ControlObjectClient_getCtlValType(IntPtr self);
- [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ [DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ private static extern int ControlObjectClient_getLastError (IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool ControlObjectClient_operate(IntPtr self, IntPtr ctlVal, UInt64 operTime);
@@ -190,7 +190,7 @@ namespace IEC61850
public delegate void CommandTerminationHandler (Object parameter, ControlObject controlObject);
private IedConnection iedConnection;
- private IntPtr controlObject;
+ private IntPtr self;
private CommandTerminationHandler commandTerminationHandler = null;
private Object commandTerminationHandlerParameter = null;
@@ -207,14 +207,14 @@ namespace IEC61850
{
this.iedConnection = iedConnection;
- this.controlObject = ControlObjectClient_create(objectReference, connection);
+ this.self = ControlObjectClient_create(objectReference, connection);
- if (this.controlObject == System.IntPtr.Zero)
+ if (this.self == System.IntPtr.Zero)
throw new IedConnectionException("Control object not found", 0);
intCommandTerminationHandler = new InternalCommandTerminationHandler (MyCommandTerminationHandler);
- ControlObjectClient_setCommandTerminationHandler(controlObject, intCommandTerminationHandler, controlObject);
+ ControlObjectClient_setCommandTerminationHandler(self, intCommandTerminationHandler, self);
}
///
@@ -225,7 +225,7 @@ namespace IEC61850
///
public ControlModel GetControlModel ()
{
- ControlModel controlModel = (ControlModel) ControlObjectClient_getControlModel(controlObject);
+ ControlModel controlModel = (ControlModel) ControlObjectClient_getControlModel(self);
return controlModel;
}
@@ -236,7 +236,7 @@ namespace IEC61850
/// MmsType required for the ctlVal value.
public MmsType GetCtlValType ()
{
- MmsType ctlValType = (MmsType) ControlObjectClient_getCtlValType (controlObject);
+ MmsType ctlValType = (MmsType) ControlObjectClient_getCtlValType (self);
return ctlValType;
}
@@ -252,7 +252,17 @@ namespace IEC61850
///
public void SetOrigin (string originator, OrCat originatorCategory)
{
- ControlObjectClient_setOrigin(controlObject, originator, (int) originatorCategory);
+ ControlObjectClient_setOrigin(self, originator, (int) originatorCategory);
+ }
+
+ ///
+ /// Gets the error code of the last synchronous control action (operate, select, select-with-value, cancel)
+ ///
+ /// error code.
+ public IedClientError LastError {
+ get {
+ return (IedClientError)ControlObjectClient_getLastError (self);
+ }
}
///
@@ -342,7 +352,7 @@ namespace IEC61850
/// true when the operation has been successful, false otherwise
public bool Operate (MmsValue ctlVal, UInt64 operTime)
{
- return ControlObjectClient_operate(controlObject, ctlVal.valueReference, operTime);
+ return ControlObjectClient_operate(self, ctlVal.valueReference, operTime);
}
private void nativeOperateHandler (UInt32 invokeId, IntPtr parameter, int err, int type, bool success)
@@ -477,7 +487,7 @@ namespace IEC61850
GCHandle handle = GCHandle.Alloc(callbackInfo);
- UInt32 invokeId = ControlObjectClient_operateAsync(controlObject, out error, ctlVal.valueReference, operTime, nativeOperateHandler, GCHandle.ToIntPtr(handle));
+ UInt32 invokeId = ControlObjectClient_operateAsync(self, out error, ctlVal.valueReference, operTime, nativeOperateHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
@@ -494,7 +504,7 @@ namespace IEC61850
/// true when the selection has been successful, false otherwise
public bool Select ()
{
- return ControlObjectClient_select(controlObject);
+ return ControlObjectClient_select(self);
}
///
@@ -512,7 +522,7 @@ namespace IEC61850
GCHandle handle = GCHandle.Alloc(callbackInfo);
- UInt32 invokeId = ControlObjectClient_selectAsync(controlObject, out error, nativeOperateHandler, GCHandle.ToIntPtr(handle));
+ UInt32 invokeId = ControlObjectClient_selectAsync(self, out error, nativeOperateHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
@@ -530,7 +540,7 @@ namespace IEC61850
/// true when the selection has been successful, false otherwise
public bool SelectWithValue (MmsValue ctlVal)
{
- return ControlObjectClient_selectWithValue(controlObject, ctlVal.valueReference);
+ return ControlObjectClient_selectWithValue(self, ctlVal.valueReference);
}
///
@@ -624,7 +634,7 @@ namespace IEC61850
GCHandle handle = GCHandle.Alloc(callbackInfo);
- UInt32 invokeId = ControlObjectClient_selectWithValueAsync(controlObject, out error, ctlVal.valueReference, nativeOperateHandler, GCHandle.ToIntPtr(handle));
+ UInt32 invokeId = ControlObjectClient_selectWithValueAsync(self, out error, ctlVal.valueReference, nativeOperateHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
@@ -645,7 +655,7 @@ namespace IEC61850
/// This exception is thrown if there is a connection or service error
public bool Cancel ()
{
- return ControlObjectClient_cancel(controlObject);
+ return ControlObjectClient_cancel(self);
}
///
@@ -659,7 +669,7 @@ namespace IEC61850
GCHandle handle = GCHandle.Alloc(callbackInfo);
- UInt32 invokeId = ControlObjectClient_cancelAsync(controlObject, out error, nativeOperateHandler, GCHandle.ToIntPtr(handle));
+ UInt32 invokeId = ControlObjectClient_cancelAsync(self, out error, nativeOperateHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
@@ -676,7 +686,7 @@ namespace IEC61850
[Obsolete("use SetSynchroCheck instead")]
public void EnableSynchroCheck ()
{
- ControlObjectClient_setSynchroCheck (controlObject, true);
+ ControlObjectClient_setSynchroCheck (self, true);
}
///
@@ -685,7 +695,7 @@ namespace IEC61850
[Obsolete("use SetInterlockCheck instead")]
public void EnableInterlockCheck ()
{
- ControlObjectClient_setInterlockCheck (controlObject, true);
+ ControlObjectClient_setInterlockCheck (self, true);
}
///
@@ -693,7 +703,7 @@ namespace IEC61850
///
public void SetInterlockCheck (bool value)
{
- ControlObjectClient_setInterlockCheck (controlObject, value);
+ ControlObjectClient_setInterlockCheck (self, value);
}
///
@@ -701,7 +711,7 @@ namespace IEC61850
///
public void SetSynchroCheck (bool value)
{
- ControlObjectClient_setSynchroCheck (controlObject, value);
+ ControlObjectClient_setSynchroCheck (self, value);
}
///
@@ -709,7 +719,7 @@ namespace IEC61850
///
public void SetTestMode (bool value)
{
- ControlObjectClient_setTestMode (controlObject, value);
+ ControlObjectClient_setTestMode (self, value);
}
///
@@ -720,7 +730,7 @@ namespace IEC61850
///
public LastApplError GetLastApplError ()
{
- LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(controlObject);
+ LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(self);
return new LastApplError(lastApplError);
}
@@ -741,9 +751,9 @@ namespace IEC61850
}
protected virtual void Dispose(bool disposing) {
- if (this.controlObject != System.IntPtr.Zero) {
- ControlObjectClient_destroy (controlObject);
- this.controlObject = System.IntPtr.Zero;
+ if (this.self != System.IntPtr.Zero) {
+ ControlObjectClient_destroy (self);
+ this.self = System.IntPtr.Zero;
}
}
diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
index 4f613bb9..6a0f8ae9 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
@@ -1,7 +1,7 @@
/*
* IEC61850ClientAPI.cs
*
- * Copyright 2014-2016 Michael Zillgith
+ * Copyright 2014-2019 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -29,14 +29,10 @@ using System.Collections;
using IEC61850.Common;
using IEC61850.TLS;
-///
-/// IEC 61850 API for the libiec61850 .NET wrapper library
-///
+// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
{
- ///
- /// IEC 61850 client API.
- ///
+ // IEC 61850 client API.
namespace Client
{
@@ -201,7 +197,9 @@ namespace IEC61850
}
}
-
+ ///
+ /// Represents a variable in a log entry
+ ///
public class MmsJournalVariable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
@@ -265,6 +263,10 @@ namespace IEC61850
this.self = self;
}
+ ///
+ /// Gets the journal variables.
+ ///
+ /// The journal variables.
public List GetJournalVariables()
{
if (variables == null)
@@ -289,7 +291,10 @@ namespace IEC61850
return variables;
}
-
+ ///
+ /// Gets the entry identifier of the log entry
+ ///
+ /// The entry identifier.
public byte[] GetEntryID()
{
IntPtr mmsValuePtr = MmsJournalEntry_getEntryID(self);
@@ -301,6 +306,10 @@ namespace IEC61850
return octetString;
}
+ ///
+ /// Gets the occurence time of the log entry
+ ///
+ /// The occurence time.
public ulong GetOccurenceTime()
{
IntPtr mmsValuePtr = MmsJournalEntry_getOccurenceTime(self);
@@ -310,6 +319,9 @@ namespace IEC61850
return mmsValue.GetBinaryTimeAsUtcMs();
}
+ ///
+ /// Releases all resource used by the object.
+ ///
public void Dispose()
{
if (self != IntPtr.Zero)
diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
index efff22ef..683d646b 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
@@ -21,26 +21,21 @@
* See COPYING file for the complete license text.
*/
using System;
-using System.Text;
-using System.Runtime.InteropServices;
using System.Collections.Generic;
-using System.Collections;
-
+using System.Runtime.InteropServices;
using IEC61850.Common;
using IEC61850.TLS;
-///
-/// IEC 61850 API for the libiec61850 .NET wrapper library
-///
+// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
{
- ///
- /// IEC 61850 server API.
- ///
- namespace Server
- {
-
- public class ConfigFileParser
+ // IEC 61850 server API.
+ namespace Server
+ {
+ ///
+ /// Config file parser.
+ ///
+ public class ConfigFileParser
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
@@ -69,6 +64,9 @@ namespace IEC61850
}
}
+ ///
+ /// Representation of the IED server data model
+ ///
public class IedModel
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
@@ -93,6 +91,10 @@ namespace IEC61850
this.self = self;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// IED name
public IedModel(string name)
{
self = IedModel_create(name);
@@ -159,8 +161,6 @@ namespace IEC61850
return getModelNodeFromNodeRef (nodeRef);
}
-
-
}
public class LogicalDevice : ModelNode
@@ -483,8 +483,6 @@ namespace IEC61850
public class ClientConnection
{
-
-
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientConnection_getPeerAddress(IntPtr self);
@@ -505,6 +503,99 @@ namespace IEC61850
}
}
+ ///
+ /// Represents additional context information of the control action that caused the callback invokation
+ ///
+ public class ControlAction
+ {
+ [DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void ControlAction_setAddCause (IntPtr self, int addCause);
+
+ [DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern int ControlAction_getOrCat (IntPtr self);
+
+ [DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr ControlAction_getOrIdent (IntPtr self, ref int size);
+
+ [DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr ControlAction_getClientConnection (IntPtr self);
+
+ private IntPtr self;
+ private IedServer.ControlHandlerInfo info;
+ private IedServer iedServer;
+
+ internal ControlAction (IntPtr self, IedServer.ControlHandlerInfo info, IedServer iedServer)
+ {
+ this.self = self;
+ this.info = info;
+ this.iedServer = iedServer;
+ }
+
+ ///
+ /// Sets the add cause for the next command termination or application error message
+ ///
+ /// the additional cause code
+ public void SetAddCause (ControlAddCause addCause)
+ {
+ ControlAction_setAddCause (self, (int)addCause);
+ }
+
+ ///
+ /// Gets the originator category provided by the client
+ ///
+ /// The or cat.
+ public OrCat GetOrCat ()
+ {
+ return (OrCat)ControlAction_getOrCat (self);
+ }
+
+ ///
+ /// Get the originator identifier provided by the client
+ ///
+ /// The or ident.
+ public byte [] GetOrIdent ()
+ {
+ int size = 0;
+
+ IntPtr orIdentPtr = ControlAction_getOrIdent (self, ref size);
+
+ if (orIdentPtr == IntPtr.Zero)
+ return null;
+
+ byte [] orIdent = new byte [size];
+
+ Marshal.Copy (orIdentPtr, orIdent, 0, size);
+
+ return orIdent;
+ }
+
+ ///
+ /// Gets the control object that is subject to this action
+ ///
+ /// the controllable data object instance
+ public DataObject GetControlObject ()
+ {
+ return info.controlObject;
+ }
+
+ ///
+ /// Gets the client object associated with the client that caused the control action
+ ///
+ /// The client connection.
+ public ClientConnection GetClientConnection ()
+ {
+ ClientConnection con = null;
+
+ IntPtr conPtr = ControlAction_getClientConnection (self);
+
+ if (conPtr != IntPtr.Zero) {
+ iedServer.clientConnections.TryGetValue (conPtr, out con);
+ }
+
+ return con;
+ }
+ }
+
public delegate MmsDataAccessError WriteAccessHandler (DataAttribute dataAttr, MmsValue value,
ClientConnection connection, object parameter);
@@ -523,9 +614,9 @@ namespace IEC61850
WAITING = 2
}
- public delegate ControlHandlerResult ControlWaitForExecutionHandler (DataObject controlObject, object parameter, MmsValue ctlVal, bool test, bool synchroCheck);
+ public delegate ControlHandlerResult ControlWaitForExecutionHandler (ControlAction action, object parameter, MmsValue ctlVal, bool test, bool synchroCheck);
- public delegate ControlHandlerResult ControlHandler (DataObject controlObject, object parameter, MmsValue ctlVal, bool test);
+ public delegate ControlHandlerResult ControlHandler (ControlAction action, object parameter, MmsValue ctlVal, bool test);
public enum CheckHandlerResult {
///
@@ -550,8 +641,7 @@ namespace IEC61850
OBJECT_UNDEFINED = 4
}
- public delegate CheckHandlerResult CheckHandler (DataObject controlObject, object parameter, MmsValue ctlVal, bool test, bool interlockCheck,
- ClientConnection connection);
+ public delegate CheckHandlerResult CheckHandler (ControlAction action, object parameter, MmsValue ctlVal, bool test, bool interlockCheck);
///
/// This class acts as the entry point for the IEC 61850 client API. It represents a single
@@ -615,13 +705,13 @@ namespace IEC61850
static extern IntPtr IedServer_getAttributeValue(IntPtr self, IntPtr dataAttribute);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- private delegate int InternalControlPerformCheckHandler (IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool interlockCheck, IntPtr connection);
+ private delegate int InternalControlPerformCheckHandler (IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool interlockCheck);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- private delegate int InternalControlWaitForExecutionHandler (IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool synchoCheck);
+ private delegate int InternalControlWaitForExecutionHandler (IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool synchoCheck);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- private delegate int InternalControlHandler (IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test);
+ private delegate int InternalControlHandler (IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_setWaitForExecutionHandler(IntPtr self, IntPtr node, InternalControlWaitForExecutionHandler handler, IntPtr parameter);
@@ -665,7 +755,7 @@ namespace IEC61850
private InternalControlPerformCheckHandler internalControlPerformCheckHandlerRef = null;
private InternalControlWaitForExecutionHandler internalControlWaitForExecutionHandlerRef = null;
- private class ControlHandlerInfo {
+ internal class ControlHandlerInfo {
public DataObject controlObject = null;
public GCHandle handle;
@@ -691,42 +781,46 @@ namespace IEC61850
private Dictionary controlHandlers = new Dictionary ();
- int internalControlHandler (IntPtr parameter, IntPtr ctlVal, bool test)
+ int InternalControlHandlerImpl (IntPtr action, IntPtr parameter, IntPtr ctlVal, bool test)
{
GCHandle handle = GCHandle.FromIntPtr (parameter);
ControlHandlerInfo info = (ControlHandlerInfo)handle.Target;
+ ControlAction controlAction = new ControlAction (action, info, this);
+
if (info != null & info.controlHandler != null)
- return (int)info.controlHandler (info.controlObject, info.controlHandlerParameter, new MmsValue (ctlVal), test);
+ return (int)info.controlHandler (controlAction, info.controlHandlerParameter, new MmsValue (ctlVal), test);
else
return (int)ControlHandlerResult.FAILED;
}
- int internalCheckHandler(IntPtr parameter, IntPtr ctlVal, bool test, bool interlockCheck, IntPtr connection)
+ int InternalCheckHandlerImpl(IntPtr action, IntPtr parameter, IntPtr ctlVal, bool test, bool interlockCheck)
{
GCHandle handle = GCHandle.FromIntPtr (parameter);
ControlHandlerInfo info = (ControlHandlerInfo)handle.Target;
if (info != null & info.checkHandler != null) {
- ClientConnection con = null;
- clientConnections.TryGetValue (connection, out con);
+ ControlAction controlAction = new ControlAction (action, info, this);
- return (int)info.checkHandler (info.controlObject, info.checkHandlerParameter, new MmsValue (ctlVal), test, interlockCheck, con);
+ return (int)info.checkHandler (controlAction, info.checkHandlerParameter, new MmsValue (ctlVal), test, interlockCheck);
} else
return (int)CheckHandlerResult.OBJECT_UNDEFINED;
}
- int internalControlWaitForExecutionHandler (IntPtr parameter, IntPtr ctlVal, bool test, bool synchoCheck)
+ int InternalControlWaitForExecutionHandlerImpl (IntPtr action, IntPtr parameter, IntPtr ctlVal, bool test, bool synchoCheck)
{
GCHandle handle = GCHandle.FromIntPtr (parameter);
ControlHandlerInfo info = (ControlHandlerInfo)handle.Target;
if (info != null & info.waitForExecHandler != null) {
- return (int)info.waitForExecHandler (info.controlObject, info.waitForExecHandlerParameter, new MmsValue (ctlVal), test, synchoCheck);
+
+ ControlAction controlAction = new ControlAction (action, info, this);
+
+ return (int)info.waitForExecHandler (controlAction, info.waitForExecHandlerParameter, new MmsValue (ctlVal), test, synchoCheck);
}
else
return (int)ControlHandlerResult.FAILED;
@@ -745,7 +839,7 @@ namespace IEC61850
}
}
- int writeAccessHandler (IntPtr dataAttribute, IntPtr value, IntPtr connection, IntPtr parameter)
+ int WriteAccessHandlerImpl (IntPtr dataAttribute, IntPtr value, IntPtr connection, IntPtr parameter)
{
//object info = writeAccessHandlers.Item [dataAttribute];
WriteAccessHandlerInfo info;
@@ -761,7 +855,7 @@ namespace IEC61850
private Dictionary writeAccessHandlers = new Dictionary ();
- private void connectionIndicationHandler (IntPtr iedServer, IntPtr clientConnection, bool connected, IntPtr parameter)
+ private void ConnectionIndicationHandlerImpl (IntPtr iedServer, IntPtr clientConnection, bool connected, IntPtr parameter)
{
if (connected == false) {
ClientConnection con = null;
@@ -785,9 +879,7 @@ namespace IEC61850
}
}
- private Dictionary clientConnections = new Dictionary ();
-
-
+ internal Dictionary clientConnections = new Dictionary ();
public IedServer(IedModel iedModel, IedServerConfig config = null)
{
@@ -849,7 +941,7 @@ namespace IEC61850
public void Start(int tcpPort)
{
if (internalConnectionHandler == null)
- internalConnectionHandler = new InternalConnectionHandler (connectionIndicationHandler);
+ internalConnectionHandler = new InternalConnectionHandler (ConnectionIndicationHandlerImpl);
IedServer_setConnectionIndicationHandler (self, internalConnectionHandler, IntPtr.Zero);
@@ -910,7 +1002,7 @@ namespace IEC61850
info.controlHandlerParameter = parameter;
if (internalControlHandlerRef == null)
- internalControlHandlerRef = new InternalControlHandler (internalControlHandler);
+ internalControlHandlerRef = new InternalControlHandler (InternalControlHandlerImpl);
IedServer_setControlHandler(self, controlObject.self, internalControlHandlerRef, GCHandle.ToIntPtr(info.handle));
}
@@ -923,7 +1015,7 @@ namespace IEC61850
info.checkHandlerParameter = parameter;
if (internalControlPerformCheckHandlerRef == null)
- internalControlPerformCheckHandlerRef = new InternalControlPerformCheckHandler (internalCheckHandler);
+ internalControlPerformCheckHandlerRef = new InternalControlPerformCheckHandler (InternalCheckHandlerImpl);
IedServer_setPerformCheckHandler(self, controlObject.self, internalControlPerformCheckHandlerRef, GCHandle.ToIntPtr(info.handle));
}
@@ -936,7 +1028,7 @@ namespace IEC61850
info.waitForExecHandlerParameter = parameter;
if (internalControlWaitForExecutionHandlerRef == null)
- internalControlWaitForExecutionHandlerRef = new InternalControlWaitForExecutionHandler (internalControlWaitForExecutionHandler);
+ internalControlWaitForExecutionHandlerRef = new InternalControlWaitForExecutionHandler (InternalControlWaitForExecutionHandlerImpl);
IedServer_setWaitForExecutionHandler(self, controlObject.self, internalControlWaitForExecutionHandlerRef, GCHandle.ToIntPtr(info.handle));
}
@@ -946,7 +1038,7 @@ namespace IEC61850
writeAccessHandlers.Add (dataAttr.self, new WriteAccessHandlerInfo(handler, parameter, dataAttr));
//writeAccessHandlers.Item [dataAttr.self] = handler;
- IedServer_handleWriteAccess (self, dataAttr.self, writeAccessHandler, IntPtr.Zero);
+ IedServer_handleWriteAccess (self, dataAttr.self, WriteAccessHandlerImpl, IntPtr.Zero);
}
public void SetWriteAccessPolicy(FunctionalConstraint fc, AccessPolicy policy)
diff --git a/dotnet/IEC61850forCSharp/MmsValue.cs b/dotnet/IEC61850forCSharp/MmsValue.cs
index 79f570a0..12b6f091 100644
--- a/dotnet/IEC61850forCSharp/MmsValue.cs
+++ b/dotnet/IEC61850forCSharp/MmsValue.cs
@@ -521,9 +521,12 @@ namespace IEC61850
if ((elementType == MmsType.MMS_ARRAY) || (elementType == MmsType.MMS_STRUCTURE)) {
if ((index >= 0) && (index < Size ())) {
- MmsValue_setElement (valueReference, index, elementValue.valueReference);
-
- } else
+ if (elementValue != null)
+ MmsValue_setElement (valueReference, index, elementValue.valueReference);
+ else
+ MmsValue_setElement (valueReference, index, IntPtr.Zero);
+
+ } else
throw new MmsValueException ("Index out of bounds");
} else
diff --git a/dotnet/server1/Program.cs b/dotnet/server1/Program.cs
index 62c7c5e3..a5910937 100644
--- a/dotnet/server1/Program.cs
+++ b/dotnet/server1/Program.cs
@@ -31,7 +31,7 @@ namespace server1
IedServer iedServer = new IedServer (iedModel, config);
- iedServer.SetControlHandler (spcso1, delegate(DataObject controlObject, object parameter, MmsValue ctlVal, bool test) {
+ iedServer.SetControlHandler (spcso1, delegate(ControlAction action, object parameter, MmsValue ctlVal, bool test) {
bool val = ctlVal.GetBoolean();
if (val)
diff --git a/dotnet/tests/Test.cs b/dotnet/tests/Test.cs
index d1c38871..934bfe71 100644
--- a/dotnet/tests/Test.cs
+++ b/dotnet/tests/Test.cs
@@ -126,7 +126,11 @@ namespace tests
Assert.AreEqual (elem2.GetType (), MmsType.MMS_INTEGER);
Assert.AreEqual (elem2.ToInt32 (), 3);
- }
+
+ val.SetElement (0, null);
+ val.SetElement (1, null);
+ val.SetElement (2, null);
+ }
[Test()]
public void MmsValueStructure()
@@ -147,6 +151,9 @@ namespace tests
MmsValue elem1 = val.GetElement (1);
Assert.AreEqual (elem1.GetType (), MmsType.MMS_BIT_STRING);
+
+ val.SetElement (0, null);
+ val.SetElement (1, null);
}
[Test ()]
@@ -428,7 +435,17 @@ namespace tests
IedServer iedServer = new IedServer (iedModel);
- iedServer.SetControlHandler (spcso1, delegate(DataObject controlObject, object parameter, MmsValue ctlVal, bool test) {
+ iedServer.SetControlHandler (spcso1, delegate(ControlAction action, object parameter, MmsValue ctlVal, bool test) {
+
+ byte [] orIdent = action.GetOrIdent ();
+
+ string orIdentStr = System.Text.Encoding.UTF8.GetString (orIdent, 0, orIdent.Length);
+
+ Assert.AreEqual ("TEST1234", orIdentStr);
+ Assert.AreEqual (OrCat.MAINTENANCE, action.GetOrCat ());
+
+ Assert.AreSame (spcso1, action.GetControlObject ());
+
handlerCalled++;
return ControlHandlerResult.OK;
}, null);
@@ -440,6 +457,7 @@ namespace tests
connection.Connect ("localhost", 10002);
ControlObject controlClient = connection.CreateControlObject ("simpleIOGenericIO/GGIO1.SPCSO1");
+ controlClient.SetOrigin ("TEST1234", OrCat.MAINTENANCE);
Assert.IsNotNull (controlClient);
diff --git a/dotnet/tls_server_example/Program.cs b/dotnet/tls_server_example/Program.cs
index e7aa0cfc..115cc100 100644
--- a/dotnet/tls_server_example/Program.cs
+++ b/dotnet/tls_server_example/Program.cs
@@ -46,7 +46,7 @@ namespace tls_server_example
IedServer iedServer = new IedServer (iedModel, tlsConfig);
- iedServer.SetControlHandler (spcso1, delegate(DataObject controlObject, object parameter, MmsValue ctlVal, bool test) {
+ iedServer.SetControlHandler (spcso1, delegate(ControlAction action, object parameter, MmsValue ctlVal, bool test) {
bool val = ctlVal.GetBoolean();
if (val)
diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h
index cd4336fb..63c668f1 100644
--- a/src/iec61850/inc/iec61850_server.h
+++ b/src/iec61850/inc/iec61850_server.h
@@ -1086,7 +1086,7 @@ typedef enum {
typedef void* ControlAction;
/**
- * \brief Set the add cause for the next command termination or application error message
+ * \brief Sets the add cause for the next command termination or application error message
*
* \param self the control action instance
* \param addCause the additional cause
@@ -1095,7 +1095,7 @@ LIB61850_API void
ControlAction_setAddCause(ControlAction self, ControlAddCause addCause);
/**
- * \brief Get the originator category provided by the client
+ * \brief Gets the originator category provided by the client
*
* \param self the control action instance
*
@@ -1105,7 +1105,7 @@ LIB61850_API int
ControlAction_getOrCat(ControlAction self);
/**
- * \brief Get the originator identifier provided by the client
+ * \brief Gets the originator identifier provided by the client
*
* \param self the control action instance
*
@@ -1115,7 +1115,7 @@ LIB61850_API uint8_t*
ControlAction_getOrIdent(ControlAction self, int* orIdentSize);
/**
- * \brief Get the client object associated with the client that caused the control action
+ * \brief Gets the client object associated with the client that caused the control action
*
* \param self the control action instance
*
@@ -1125,7 +1125,7 @@ LIB61850_API ClientConnection
ControlAction_getClientConnection(ControlAction self);
/**
- * \brief Get the control object that is subject to this action
+ * \brief Gets the control object that is subject to this action
*
* \param self the control action instance
*