diff --git a/dotnet/IEC61850forCSharp/Control.cs b/dotnet/IEC61850forCSharp/Control.cs
index c629ad90..4fa909cf 100644
--- a/dotnet/IEC61850forCSharp/Control.cs
+++ b/dotnet/IEC61850forCSharp/Control.cs
@@ -101,6 +101,13 @@ namespace IEC61850
}
}
+ public enum ControlActionType
+ {
+ SELECT = 0,
+ OPERATE = 1,
+ CANCEL = 2
+ }
+
///
/// Control object.
///
@@ -125,6 +132,30 @@ namespace IEC61850
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool ControlObjectClient_operate(IntPtr self, IntPtr ctlVal, UInt64 operTime);
+ ///
+ /// Handler for asynchronous control actions (select, operate, cancel)
+ ///
+ public delegate void ControlActionHandler (UInt32 invokeId, Object parameter, IedClientError error, ControlActionType type, bool success);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate void ControlObjectClient_ControlActionHandler (UInt32 invokeId, IntPtr parameter, int err, int type, [MarshalAs(UnmanagedType.I1)] bool success);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ private static extern UInt32 ControlObjectClient_operateAsync(IntPtr self, out int err, IntPtr ctlVal, UInt64 operTime,
+ ControlObjectClient_ControlActionHandler handler, IntPtr parameter);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ private static extern UInt32 ControlObjectClient_selectAsync(IntPtr self, out int err,
+ ControlObjectClient_ControlActionHandler handler, IntPtr parameter);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ private static extern UInt32 ControlObjectClient_selectWithValueAsync(IntPtr self, out int err, IntPtr ctlVal,
+ ControlObjectClient_ControlActionHandler handler, IntPtr parameter);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ private static extern UInt32 ControlObjectClient_cancelAsync(IntPtr self, out int err,
+ ControlObjectClient_ControlActionHandler handler, IntPtr parameter);
+
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool ControlObjectClient_select(IntPtr self);
@@ -314,6 +345,149 @@ namespace IEC61850
return ControlObjectClient_operate(controlObject, ctlVal.valueReference, operTime);
}
+ private void nativeOperateHandler (UInt32 invokeId, IntPtr parameter, int err, int type, bool success)
+ {
+ GCHandle handle = GCHandle.FromIntPtr(parameter);
+
+ Tuple callbackInfo = handle.Target as Tuple;
+
+ ControlActionHandler handler = callbackInfo.Item1;
+ object handlerParameter = callbackInfo.Item2;
+
+ handle.Free();
+
+ IedClientError clientError = (IedClientError)err;
+
+ handler(invokeId, handlerParameter, clientError, (ControlActionType) type, success);
+ }
+
+
+ ///
+ /// Operate the control with the specified control value.
+ ///
+ /// the new value of the control
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 OperateAsync (bool ctlVal, ControlActionHandler handler, object parameter)
+ {
+ return OperateAsync (ctlVal, 0, handler, parameter);
+ }
+
+ ///
+ /// Operate the control with the specified control value (time activated control).
+ ///
+ /// the new value of the control
+ /// the time when the operation will be executed
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 OperateAsync (bool ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
+ {
+ MmsValue value = new MmsValue(ctlVal);
+
+ return OperateAsync (value, operTime, handler, parameter);
+ }
+
+ ///
+ /// Operate the control with the specified control value.
+ ///
+ /// the new value of the control
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 OperateAsync (float ctlVal, ControlActionHandler handler, object parameter)
+ {
+ return OperateAsync (ctlVal, 0, handler, parameter);
+ }
+
+ ///
+ /// Operate the control with the specified control value (time activated control).
+ ///
+ /// the new value of the control
+ /// the time when the operation will be executed
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 OperateAsync (float ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
+ {
+ MmsValue value = new MmsValue(ctlVal);
+
+ return OperateAsync (value, operTime, handler, parameter);
+ }
+
+ ///
+ /// Operate the control with the specified control value.
+ ///
+ /// the new value of the control
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 OperateAsync (int ctlVal, ControlActionHandler handler, object parameter)
+ {
+ return OperateAsync (ctlVal, 0, handler, parameter);
+ }
+
+ ///
+ /// Operate the control with the specified control value (time activated control).
+ ///
+ /// the new value of the control
+ /// the time when the operation will be executed
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 OperateAsync (int ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
+ {
+ return OperateAsync (ctlVal, operTime, handler, parameter);
+ }
+
+ ///
+ /// Operate the control with the specified control value.
+ ///
+ /// the new value of the control
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 OperateAsync (MmsValue ctlVal, ControlActionHandler handler, object parameter)
+ {
+ return OperateAsync (ctlVal, 0, handler, parameter);
+ }
+
+ ///
+ /// Operate the control with the specified control value (time activated control).
+ ///
+ /// the new value of the control
+ /// the time when the operation will be executed
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 OperateAsync (MmsValue ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
+ {
+ int error;
+
+ Tuple callbackInfo = Tuple.Create(handler, parameter);
+
+ GCHandle handle = GCHandle.Alloc(callbackInfo);
+
+ UInt32 invokeId = ControlObjectClient_operateAsync(controlObject, out error, ctlVal.valueReference, operTime, nativeOperateHandler, GCHandle.ToIntPtr(handle));
+
+ if (error != 0)
+ {
+ handle.Free();
+ throw new IedConnectionException("Operate failed", error);
+ }
+
+ return invokeId;
+ }
+
///
/// Select the control object.
///
@@ -323,13 +497,36 @@ namespace IEC61850
return ControlObjectClient_select(controlObject);
}
+ ///
+ /// Select the control object.
+ ///
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 SelectAsync(ControlActionHandler handler, object parameter)
+ {
+ int error;
+
+ Tuple callbackInfo = Tuple.Create(handler, parameter);
+
+ GCHandle handle = GCHandle.Alloc(callbackInfo);
+
+ UInt32 invokeId = ControlObjectClient_selectAsync(controlObject, out error, nativeOperateHandler, GCHandle.ToIntPtr(handle));
+
+ if (error != 0)
+ {
+ handle.Free();
+ throw new IedConnectionException("Select failed", error);
+ }
+
+ return invokeId;
+ }
///
/// Send a select with value command for generic MmsValue instances
///
- ///
- /// the value to be checked.
- ///
+ /// the value to be checked.
/// true when the selection has been successful, false otherwise
public bool SelectWithValue (MmsValue ctlVal)
{
@@ -372,15 +569,107 @@ namespace IEC61850
return SelectWithValue(new MmsValue(ctlVal));
}
+ ///
+ /// Send a select with value command for boolean controls - asynchronous version
+ ///
+ /// the value to be checked.
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 SelectWithValueAsync (bool ctlVal, ControlActionHandler handler, object parameter)
+ {
+ return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
+ }
+
+ ///
+ /// Send a select with value command for integer controls - asynchronous version
+ ///
+ /// the value to be checked.
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 SelectWithValueAsync (int ctlVal, ControlActionHandler handler, object parameter)
+ {
+ return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
+ }
+
+ ///
+ /// Send a select with value command for float controls - asynchronous version
+ ///
+ /// the value to be checked.
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 SelectWithValueAsync (float ctlVal, ControlActionHandler handler, object parameter)
+ {
+ return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
+ }
+
+ ///
+ /// Send a select with value command for generic MmsValue instances - asynchronous version
+ ///
+ /// the value to be checked.
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 SelectWithValueAsync (MmsValue ctlVal, ControlActionHandler handler, object parameter)
+ {
+ int error;
+
+ Tuple callbackInfo = Tuple.Create(handler, parameter);
+
+ GCHandle handle = GCHandle.Alloc(callbackInfo);
+
+ UInt32 invokeId = ControlObjectClient_selectWithValueAsync(controlObject, out error, ctlVal.valueReference, nativeOperateHandler, GCHandle.ToIntPtr(handle));
+
+ if (error != 0)
+ {
+ handle.Free();
+ throw new IedConnectionException("Select with value failed", error);
+ }
+
+ return invokeId;
+ }
+
///
/// Cancel a selection or time activated operation
///
/// true when the cancelation has been successful, false otherwise
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
public bool Cancel ()
{
return ControlObjectClient_cancel(controlObject);
}
+ ///
+ /// Cancel a selection or time activated operation
+ ///
+ public UInt32 CancelAsync(ControlActionHandler handler, object parameter)
+ {
+ int error;
+
+ Tuple callbackInfo = Tuple.Create(handler, parameter);
+
+ GCHandle handle = GCHandle.Alloc(callbackInfo);
+
+ UInt32 invokeId = ControlObjectClient_cancelAsync(controlObject, out error, nativeOperateHandler, GCHandle.ToIntPtr(handle));
+
+ if (error != 0)
+ {
+ handle.Free();
+ throw new IedConnectionException("Cancel failed", error);
+ }
+
+ return invokeId;
+ }
+
///
/// Enables the synchro check for operate commands
///
diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
index b919cfeb..7d251e51 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
@@ -544,6 +544,23 @@ namespace IEC61850
static extern UInt32
IedConnection_queryLogAfterAsync(IntPtr self, out int error, string logReference,
IntPtr entryID, UInt64 timeStamp, IedConnection_QueryLogHandler handler, IntPtr parameter);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate void IedConnection_GetVariableSpecificationHandler (UInt32 invokeId, IntPtr parameter, int err, IntPtr spec);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern UInt32
+ IedConnection_getVariableSpecificationAsync(IntPtr self, out int error, string dataAttributeReference,
+ int fc, IedConnection_GetVariableSpecificationHandler handler, IntPtr parameter);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate void IedConnection_ReadDataSetHandler (UInt32 invokeId, IntPtr parameter, int err, IntPtr dataSet);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern UInt32
+ IedConnection_readDataSetValuesAsync(IntPtr self, out int error, string dataSetReference, IntPtr dataSet,
+ IedConnection_ReadDataSetHandler handler, IntPtr parameter);
+
/********************
* FileDirectoryEntry
@@ -1330,8 +1347,10 @@ namespace IEC61850
/// Read the content of a file directory. - single request version
/// The name of the directory.
+ /// the filename that defines the continuation point, or null for the first request
+ /// true, when more files are available, false otherwise
/// This exception is thrown if there is a connection or service error
- /// The name of the directory.
+
public List GetFileDirectoryEx(string directoryName, string continueAfter, out bool moreFollows)
{
int error;
@@ -1567,7 +1586,6 @@ namespace IEC61850
/// This function will invoke a readDataSetValues service and return a new DataSet value containing the
/// received values.
/// The object reference of the data set
-
/// This exception is thrown if there is a connection or service error
public DataSet GetDataSetValues (string dataSetReference)
{
@@ -1810,6 +1828,119 @@ namespace IEC61850
return invokeId;
}
+ private void nativeGetVariableSpecifcationHandler (UInt32 invokeId, IntPtr parameter, int err, IntPtr spec)
+ {
+ GCHandle handle = GCHandle.FromIntPtr(parameter);
+
+ Tuple callbackInfo = handle.Target as Tuple;
+
+ GetVariableSpecifcationHandler handler = callbackInfo.Item1;
+ object handlerParameter = callbackInfo.Item2;
+
+ handle.Free();
+
+ IedClientError clientError = (IedClientError)err;
+
+ MmsVariableSpecification varSpec = null;
+
+ if (spec != IntPtr.Zero)
+ varSpec = new MmsVariableSpecification(spec, true);
+
+ handler(invokeId, handlerParameter, clientError, varSpec);
+ }
+
+ public delegate void GetVariableSpecifcationHandler(UInt32 invokeId, object parameter, IedClientError err, MmsVariableSpecification spec);
+
+ /// Read the variable specification (type description of a DA or FCDO
+ /// The object reference of a DA or FCDO.
+ /// The functional constraint (FC) of the object
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 GetVariableSpecificationAsync(string objectReference, FunctionalConstraint fc, GetVariableSpecifcationHandler handler, object parameter)
+ {
+ int error;
+
+ Tuple callbackInfo = Tuple.Create(handler, parameter);
+
+ GCHandle handle = GCHandle.Alloc(callbackInfo);
+
+ UInt32 invokeId = IedConnection_getVariableSpecificationAsync(connection, out error, objectReference, (int)fc, nativeGetVariableSpecifcationHandler, GCHandle.ToIntPtr(handle));
+
+ if (error != 0)
+ {
+ handle.Free();
+ throw new IedConnectionException("Reading variable specification failed", error);
+ }
+
+ return invokeId;
+ }
+
+ private void nativeReadDataSetHandler (UInt32 invokeId, IntPtr parameter, int err, IntPtr nativeDataSet)
+ {
+ GCHandle handle = GCHandle.FromIntPtr(parameter);
+
+ Tuple callbackInfo = handle.Target as Tuple;
+
+ ReadDataSetHandler handler = callbackInfo.Item1;
+ object handlerParameter = callbackInfo.Item2;
+ DataSet dataSet = callbackInfo.Item3;
+
+ handle.Free();
+
+ IedClientError clientError = (IedClientError)err;
+
+ if (nativeDataSet != IntPtr.Zero)
+ {
+ if (dataSet == null)
+ dataSet = new DataSet(nativeDataSet);
+ }
+
+
+ handler(invokeId, handlerParameter, clientError, dataSet);
+ }
+
+
+ public delegate void ReadDataSetHandler(UInt32 invokeId, object parameter, IedClientError err, DataSet dataSet);
+
+ ///
+ /// Read the values of a data set (GetDataSetValues service) - asynchronous version
+ ///
+ /// This function will invoke a readDataSetValues service and in case of success returns a new DataSet value
+ /// containing the received values by the callback function. If an existing instance of DataSet is provided to the
+ /// function the existing instance will be updated by the new values.
+ ///
+ /// The object reference of the data set
+ /// The object reference of an existing data set instance or null
+ /// Callback function to handle the received response or service timeout
+ /// User provided callback parameter. Will be passed to the callback function
+ /// the invoke ID of the sent request
+ /// This exception is thrown if there is a connection or service error
+ public UInt32 ReadDataSetValuesAsync(string dataSetReference, DataSet dataSet, ReadDataSetHandler handler, object parameter)
+ {
+ int error;
+
+ Tuple callbackInfo = Tuple.Create(handler, parameter, dataSet);
+
+ GCHandle handle = GCHandle.Alloc(callbackInfo);
+
+ IntPtr dataSetPtr = IntPtr.Zero;
+
+ if (dataSet != null)
+ dataSetPtr = dataSet.getNativeInstance();
+
+ UInt32 invokeId = IedConnection_readDataSetValuesAsync(connection, out error, dataSetReference, dataSetPtr, nativeReadDataSetHandler, GCHandle.ToIntPtr(handle));
+
+ if (error != 0)
+ {
+ handle.Free();
+ throw new IedConnectionException("Reading data set failed", error);
+ }
+
+ return invokeId;
+ }
+
///
/// Write value handler.
///