Merge branch 'v1.6_develop' of bitbucket.com:mz-automation/libiec61850 into v1.6_develop

v1.6
Michael Zillgith 4 weeks ago
commit 3da8aa5222

@ -0,0 +1,205 @@
/*
* AcseAuthenticationParameter.cs
*
* Copyright 2025-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
using System;
using System.Runtime.InteropServices;
using System.Text;
// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
{
/// <summary>
/// Authentication mechanism used by AcseAuthenticator
/// </summary>
public enum AcseAuthenticationMechanism
{
/** Neither ACSE nor TLS authentication used */
ACSE_AUTH_NONE = 0,
/** Use ACSE password for client authentication */
ACSE_AUTH_PASSWORD = 1,
/** Use ACSE certificate for client authentication */
ACSE_AUTH_CERTIFICATE = 2,
/** Use TLS certificate for client authentication */
ACSE_AUTH_TLS = 3
}
public class AcseAuthenticationParameter
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr AcseAuthenticationParameter_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void AcseAuthenticationParameter_setAuthMechanism(IntPtr self, int mechanism);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void AcseAuthenticationParameter_setPassword(IntPtr self, string password);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int AcseAuthenticationParameter_getAuthMechanism(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr AcseAuthenticationParameter_getPassword(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int AcseAuthenticationParameter_getPasswordLength(IntPtr self);
private IntPtr self = IntPtr.Zero;
public AcseAuthenticationParameter()
{
self = AcseAuthenticationParameter_create();
}
public AcseAuthenticationParameter(IntPtr self)
{
this.self = self;
}
public void SetAuthMechanism(AcseAuthenticationMechanism acseAuthenticationMechanism)
{
AcseAuthenticationParameter_setAuthMechanism(self, (int)acseAuthenticationMechanism);
}
public void SetPassword(string password)
{
AcseAuthenticationParameter_setPassword(self, password);
}
public AcseAuthenticationMechanism GetAuthMechanism()
{
return (AcseAuthenticationMechanism)AcseAuthenticationParameter_getAuthMechanism(self);
}
public string GetPasswordString()
{
try
{
byte[] password = GetPasswordByteArray();
return Encoding.UTF8.GetString(password);
}
catch (Exception)
{
return null;
}
}
public byte[] GetPasswordByteArray()
{
IntPtr password = AcseAuthenticationParameter_getPassword(self);
if (password != IntPtr.Zero)
{
int lenght = GetPasswordLenght();
byte[] result = new byte[lenght];
Marshal.Copy(password, result, 0, lenght);
return result;
}
else
return null;
}
public int GetPasswordLenght()
{
return AcseAuthenticationParameter_getPasswordLength(self);
}
}
public class IsoApplicationReference
{
private IntPtr self = IntPtr.Zero;
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int IsoApplicationReference_getAeQualifier(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IsoApplicationReference_getApTitle(IntPtr self);
public IsoApplicationReference(IntPtr self)
{
this.self = self;
}
public int GetAeQualifier()
{
return IsoApplicationReference_getAeQualifier(self);
}
public ItuObjectIdentifier GetApTitle()
{
IntPtr identfier = IsoApplicationReference_getApTitle(self);
if (identfier == IntPtr.Zero)
return null;
return new ItuObjectIdentifier(identfier);
}
}
public class ItuObjectIdentifier
{
private IntPtr self = IntPtr.Zero;
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ItuObjectIdentifier_getArcCount(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ItuObjectIdentifier_getArc(IntPtr self);
public ItuObjectIdentifier(IntPtr self)
{
this.self = self;
}
public int GetArcCount()
{
return ItuObjectIdentifier_getArcCount(self);
}
public ushort[] GetArcs()
{
int count = ItuObjectIdentifier_getArcCount(self);
if (count <= 0 || count > 10) return Array.Empty<ushort>();
IntPtr arcPtr = ItuObjectIdentifier_getArc(self);
ushort[] arcs = new ushort[count];
short[] temp = new short[count];
Marshal.Copy(arcPtr, temp, 0, count);
for (int i = 0; i < count; i++)
arcs[i] = (ushort)temp[i];
return arcs;
}
}
}

@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

@ -1,7 +1,7 @@
/*
* Control.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,15 +21,15 @@
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850
{
// IEC 61850 common API parts (used by client and server API)
namespace Common {
namespace Common
{
/// <summary>
/// Control model
@ -39,7 +39,7 @@ namespace IEC61850
/** status only */
STATUS_ONLY = 0,
/** direct with normal security */
DIRECT_NORMAL= 1,
DIRECT_NORMAL = 1,
/** select before operate (SBO) with normal security */
SBO_NORMAL = 2,
/** direct with enhanced security */
@ -51,7 +51,8 @@ namespace IEC61850
/// <summary>
/// Originator category
/// </summary>
public enum OrCat {
public enum OrCat
{
/** Not supported - should not be used */
NOT_SUPPORTED = 0,
/** Control operation issued from an operator using a client located at bay level */
@ -90,11 +91,11 @@ namespace IEC61850
public ControlAddCause addCause;
internal LastApplError (LastApplErrorInternal lastApplError)
internal LastApplError(LastApplErrorInternal lastApplError)
{
this.addCause = (ControlAddCause) lastApplError.addCause;
this.error = lastApplError.error;
this.ctlNum = lastApplError.ctlNum;
addCause = (ControlAddCause)lastApplError.addCause;
error = lastApplError.error;
ctlNum = lastApplError.ctlNum;
}
}
@ -125,8 +126,8 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern int ControlObjectClient_getCtlValType(IntPtr self);
[DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern int ControlObjectClient_getLastError (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern int ControlObjectClient_getLastError(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
@ -135,10 +136,10 @@ namespace IEC61850
/// <summary>
/// Handler for asynchronous control actions (select, operate, cancel)
/// </summary>
public delegate void ControlActionHandler (UInt32 invokeId, Object parameter, IedClientError error, ControlActionType type, bool success);
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);
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,
@ -181,13 +182,13 @@ namespace IEC61850
private static extern void ControlObjectClient_setTestMode(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalCommandTerminationHandler(IntPtr parameter,IntPtr controlClient);
private delegate void InternalCommandTerminationHandler(IntPtr parameter, IntPtr controlClient);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_setCommandTerminationHandler(IntPtr self,
InternalCommandTerminationHandler handler, IntPtr handlerParameter);
public delegate void CommandTerminationHandler (Object parameter, ControlObject controlObject);
public delegate void CommandTerminationHandler(Object parameter, ControlObject controlObject);
private IedConnection iedConnection;
private IntPtr self;
@ -195,7 +196,7 @@ namespace IEC61850
private CommandTerminationHandler commandTerminationHandler = null;
private Object commandTerminationHandlerParameter = null;
private void MyCommandTerminationHandler (IntPtr paramter, IntPtr controlClient)
private void MyCommandTerminationHandler(IntPtr paramter, IntPtr controlClient)
{
if (commandTerminationHandler != null)
commandTerminationHandler(commandTerminationHandlerParameter, this);
@ -203,16 +204,16 @@ namespace IEC61850
private InternalCommandTerminationHandler intCommandTerminationHandler;
internal ControlObject (string objectReference, IntPtr connection, IedConnection iedConnection)
internal ControlObject(string objectReference, IntPtr connection, IedConnection iedConnection)
{
this.iedConnection = iedConnection;
this.self = ControlObjectClient_create(objectReference, connection);
self = ControlObjectClient_create(objectReference, connection);
if (this.self == System.IntPtr.Zero)
if (self == System.IntPtr.Zero)
throw new IedConnectionException("Control object not found", 0);
intCommandTerminationHandler = new InternalCommandTerminationHandler (MyCommandTerminationHandler);
intCommandTerminationHandler = new InternalCommandTerminationHandler(MyCommandTerminationHandler);
ControlObjectClient_setCommandTerminationHandler(self, intCommandTerminationHandler, self);
}
@ -223,9 +224,9 @@ namespace IEC61850
/// <returns>
/// The control model.
/// </returns>
public ControlModel GetControlModel ()
public ControlModel GetControlModel()
{
ControlModel controlModel = (ControlModel) ControlObjectClient_getControlModel(self);
ControlModel controlModel = (ControlModel)ControlObjectClient_getControlModel(self);
return controlModel;
}
@ -234,9 +235,9 @@ namespace IEC61850
/// Get the type of ctlVal.
/// </summary>
/// <returns>MmsType required for the ctlVal value.</returns>
public MmsType GetCtlValType ()
public MmsType GetCtlValType()
{
MmsType ctlValType = (MmsType) ControlObjectClient_getCtlValType (self);
MmsType ctlValType = (MmsType)ControlObjectClient_getCtlValType(self);
return ctlValType;
}
@ -250,18 +251,20 @@ namespace IEC61850
/// <param name='originatorCategory'>
/// Originator category.
/// </param>
public void SetOrigin (string originator, OrCat originatorCategory)
public void SetOrigin(string originator, OrCat originatorCategory)
{
ControlObjectClient_setOrigin(self, originator, (int) originatorCategory);
ControlObjectClient_setOrigin(self, originator, (int)originatorCategory);
}
/// <summary>
/// Gets the error code of the last synchronous control action (operate, select, select-with-value, cancel)
/// </summary>
/// <value>error code.</value>
public IedClientError LastError {
get {
return (IedClientError)ControlObjectClient_getLastError (self);
public IedClientError LastError
{
get
{
return (IedClientError)ControlObjectClient_getLastError(self);
}
}
@ -270,9 +273,9 @@ namespace IEC61850
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (bool ctlVal)
public bool Operate(bool ctlVal)
{
return Operate (ctlVal, 0);
return Operate(ctlVal, 0);
}
/// <summary>
@ -281,11 +284,11 @@ namespace IEC61850
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (bool ctlVal, UInt64 operTime)
public bool Operate(bool ctlVal, UInt64 operTime)
{
MmsValue value = new MmsValue(ctlVal);
return Operate (value, operTime);
return Operate(value, operTime);
}
/// <summary>
@ -293,9 +296,9 @@ namespace IEC61850
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (float ctlVal)
public bool Operate(float ctlVal)
{
return Operate (ctlVal, 0);
return Operate(ctlVal, 0);
}
/// <summary>
@ -304,11 +307,11 @@ namespace IEC61850
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (float ctlVal, UInt64 operTime)
public bool Operate(float ctlVal, UInt64 operTime)
{
MmsValue value = new MmsValue(ctlVal);
return Operate (value, operTime);
return Operate(value, operTime);
}
/// <summary>
@ -316,9 +319,9 @@ namespace IEC61850
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (int ctlVal)
public bool Operate(int ctlVal)
{
return Operate (ctlVal, 0);
return Operate(ctlVal, 0);
}
/// <summary>
@ -327,11 +330,11 @@ namespace IEC61850
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (int ctlVal, UInt64 operTime)
public bool Operate(int ctlVal, UInt64 operTime)
{
MmsValue value = new MmsValue(ctlVal);
return Operate (value, operTime);
return Operate(value, operTime);
}
/// <summary>
@ -339,9 +342,9 @@ namespace IEC61850
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (MmsValue ctlVal)
public bool Operate(MmsValue ctlVal)
{
return Operate (ctlVal, 0);
return Operate(ctlVal, 0);
}
/// <summary>
@ -350,14 +353,14 @@ namespace IEC61850
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (MmsValue ctlVal, UInt64 operTime)
public bool Operate(MmsValue ctlVal, UInt64 operTime)
{
return ControlObjectClient_operate(self, ctlVal.valueReference, operTime);
}
private ControlObjectClient_ControlActionHandler internalOperateHandler = null;
private void nativeOperateHandler (UInt32 invokeId, IntPtr parameter, int err, int type, bool success)
private void nativeOperateHandler(UInt32 invokeId, IntPtr parameter, int err, int type, bool success)
{
GCHandle handle = GCHandle.FromIntPtr(parameter);
@ -370,7 +373,7 @@ namespace IEC61850
IedClientError clientError = (IedClientError)err;
handler(invokeId, handlerParameter, clientError, (ControlActionType) type, success);
handler(invokeId, handlerParameter, clientError, (ControlActionType)type, success);
}
@ -382,9 +385,9 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (bool ctlVal, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(bool ctlVal, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, 0, handler, parameter);
return OperateAsync(ctlVal, 0, handler, parameter);
}
/// <summary>
@ -396,11 +399,11 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (bool ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(bool ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
{
MmsValue value = new MmsValue(ctlVal);
return OperateAsync (value, operTime, handler, parameter);
return OperateAsync(value, operTime, handler, parameter);
}
/// <summary>
@ -411,9 +414,9 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (float ctlVal, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(float ctlVal, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, 0, handler, parameter);
return OperateAsync(ctlVal, 0, handler, parameter);
}
/// <summary>
@ -425,11 +428,11 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (float ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(float ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
{
MmsValue value = new MmsValue(ctlVal);
return OperateAsync (value, operTime, handler, parameter);
return OperateAsync(value, operTime, handler, parameter);
}
/// <summary>
@ -440,9 +443,9 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (int ctlVal, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(int ctlVal, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, 0, handler, parameter);
return OperateAsync(ctlVal, 0, handler, parameter);
}
/// <summary>
@ -454,9 +457,9 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (int ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(int ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, operTime, handler, parameter);
return OperateAsync(ctlVal, operTime, handler, parameter);
}
/// <summary>
@ -467,9 +470,9 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (MmsValue ctlVal, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(MmsValue ctlVal, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, 0, handler, parameter);
return OperateAsync(ctlVal, 0, handler, parameter);
}
/// <summary>
@ -481,7 +484,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (MmsValue ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(MmsValue ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
{
int error;
@ -507,7 +510,7 @@ namespace IEC61850
/// Select the control object.
/// </summary>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool Select ()
public bool Select()
{
return ControlObjectClient_select(self);
}
@ -546,7 +549,7 @@ namespace IEC61850
/// </summary>
/// <param name='ctlVal'>the value to be checked.</param>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool SelectWithValue (MmsValue ctlVal)
public bool SelectWithValue(MmsValue ctlVal)
{
return ControlObjectClient_selectWithValue(self, ctlVal.valueReference);
}
@ -558,7 +561,7 @@ namespace IEC61850
/// the value to be checked.
/// </param>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool SelectWithValue (bool ctlVal)
public bool SelectWithValue(bool ctlVal)
{
return SelectWithValue(new MmsValue(ctlVal));
}
@ -570,7 +573,7 @@ namespace IEC61850
/// the value to be checked.
/// </param>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool SelectWithValue (int ctlVal)
public bool SelectWithValue(int ctlVal)
{
return SelectWithValue(new MmsValue(ctlVal));
}
@ -582,7 +585,7 @@ namespace IEC61850
/// the value to be checked.
/// </param>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool SelectWithValue (float ctlVal)
public bool SelectWithValue(float ctlVal)
{
return SelectWithValue(new MmsValue(ctlVal));
}
@ -595,7 +598,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 SelectWithValueAsync (bool ctlVal, ControlActionHandler handler, object parameter)
public UInt32 SelectWithValueAsync(bool ctlVal, ControlActionHandler handler, object parameter)
{
return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
}
@ -608,7 +611,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 SelectWithValueAsync (int ctlVal, ControlActionHandler handler, object parameter)
public UInt32 SelectWithValueAsync(int ctlVal, ControlActionHandler handler, object parameter)
{
return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
}
@ -621,7 +624,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 SelectWithValueAsync (float ctlVal, ControlActionHandler handler, object parameter)
public UInt32 SelectWithValueAsync(float ctlVal, ControlActionHandler handler, object parameter)
{
return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
}
@ -634,7 +637,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 SelectWithValueAsync (MmsValue ctlVal, ControlActionHandler handler, object parameter)
public UInt32 SelectWithValueAsync(MmsValue ctlVal, ControlActionHandler handler, object parameter)
{
int error;
@ -664,7 +667,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public bool Cancel ()
public bool Cancel()
{
return ControlObjectClient_cancel(self);
}
@ -698,42 +701,42 @@ namespace IEC61850
/// Enables the synchro check for operate commands
/// </summary>
[Obsolete("use SetSynchroCheck instead")]
public void EnableSynchroCheck ()
public void EnableSynchroCheck()
{
ControlObjectClient_setSynchroCheck (self, true);
ControlObjectClient_setSynchroCheck(self, true);
}
/// <summary>
/// Enables the interlock check for operate and select commands
/// </summary>
[Obsolete("use SetInterlockCheck instead")]
public void EnableInterlockCheck ()
public void EnableInterlockCheck()
{
ControlObjectClient_setInterlockCheck (self, true);
ControlObjectClient_setInterlockCheck(self, true);
}
/// <summary>
/// Sets the value of the interlock check flag for operate and select commands
/// </summary>
public void SetInterlockCheck (bool value)
public void SetInterlockCheck(bool value)
{
ControlObjectClient_setInterlockCheck (self, value);
ControlObjectClient_setInterlockCheck(self, value);
}
/// <summary>
/// Sets the value of the synchro check flag for operate command
/// </summary>
public void SetSynchroCheck (bool value)
public void SetSynchroCheck(bool value)
{
ControlObjectClient_setSynchroCheck (self, value);
ControlObjectClient_setSynchroCheck(self, value);
}
/// <summary>
/// Sets the value of the test flag for the operate command
/// </summary>
public void SetTestMode (bool value)
public void SetTestMode(bool value)
{
ControlObjectClient_setTestMode (self, value);
ControlObjectClient_setTestMode(self, value);
}
/// <summary>
@ -742,7 +745,7 @@ namespace IEC61850
/// <returns>
/// The last appl error.
/// </returns>
public LastApplError GetLastApplError ()
public LastApplError GetLastApplError()
{
LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(self);
@ -758,26 +761,29 @@ namespace IEC61850
/// <param name='parameter'>
/// Parameter.
/// </param>
public void SetCommandTerminationHandler (CommandTerminationHandler handler, Object parameter)
public void SetCommandTerminationHandler(CommandTerminationHandler handler, Object parameter)
{
this.commandTerminationHandler = handler;
this.commandTerminationHandlerParameter = parameter;
commandTerminationHandler = handler;
commandTerminationHandlerParameter = parameter;
}
protected virtual void Dispose(bool disposing) {
if (this.self != System.IntPtr.Zero) {
ControlObjectClient_destroy (self);
this.self = System.IntPtr.Zero;
protected virtual void Dispose(bool disposing)
{
if (self != System.IntPtr.Zero)
{
ControlObjectClient_destroy(self);
self = System.IntPtr.Zero;
}
}
public void Dispose() {
Dispose (true);
public void Dispose()
{
Dispose(true);
}
~ControlObject()
{
Dispose (false);
Dispose(false);
}
}

@ -1,7 +1,7 @@
/*
* DataSet.cs
*
* Copyright 2014-2018 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,12 +20,10 @@
*
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850
{
namespace Client

@ -1,7 +1,7 @@
/*
* GooseControlBlock.cs
*
* Copyright 2017 Michael Zillgith
* Copyright 2017-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,69 +20,68 @@
*
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using IEC61850.Common;
namespace IEC61850
{
namespace Client
{
public class GooseControlBlock : IDisposable {
public class GooseControlBlock : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_create (string dataAttributeReference);
static extern IntPtr ClientGooseControlBlock_create(string dataAttributeReference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedConnection_getGoCBValues (IntPtr connection, out int error, string rcbReference, IntPtr updateRcb);
static extern IntPtr IedConnection_getGoCBValues(IntPtr connection, out int error, string rcbReference, IntPtr updateRcb);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_setGoCBValues (IntPtr connection, out int error, IntPtr rcb, UInt32 parametersMask, [MarshalAs(UnmanagedType.I1)] bool singleRequest);
static extern void IedConnection_setGoCBValues(IntPtr connection, out int error, IntPtr rcb, UInt32 parametersMask, [MarshalAs(UnmanagedType.I1)] bool singleRequest);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientGooseControlBlock_getGoEna (IntPtr self);
static extern bool ClientGooseControlBlock_getGoEna(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setGoEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getGoID (IntPtr self);
static extern IntPtr ClientGooseControlBlock_getGoID(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setGoID (IntPtr self, string goId);
static extern void ClientGooseControlBlock_setGoID(IntPtr self, string goId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getDatSet (IntPtr self);
static extern IntPtr ClientGooseControlBlock_getDatSet(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setDatSet (IntPtr self, string datSet);
static extern void ClientGooseControlBlock_setDatSet(IntPtr self, string datSet);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientGooseControlBlock_getConfRev (IntPtr self);
static extern UInt32 ClientGooseControlBlock_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientGooseControlBlock_getNdsComm (IntPtr self);
static extern bool ClientGooseControlBlock_getNdsComm(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientGooseControlBlock_getMinTime (IntPtr self);
static extern UInt32 ClientGooseControlBlock_getMinTime(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientGooseControlBlock_getMaxTime (IntPtr self);
static extern UInt32 ClientGooseControlBlock_getMaxTime(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientGooseControlBlock_getFixedOffs (IntPtr self);
static extern bool ClientGooseControlBlock_getFixedOffs(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern PhyComAddress ClientGooseControlBlock_getDstAddress (IntPtr self);
static extern PhyComAddress ClientGooseControlBlock_getDstAddress(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getDstAddress_addr(IntPtr self);
@ -97,7 +96,7 @@ namespace IEC61850
static extern UInt16 ClientGooseControlBlock_getDstAddress_appid(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setDstAddress (IntPtr self, PhyComAddress value);
static extern void ClientGooseControlBlock_setDstAddress(IntPtr self, PhyComAddress value);
private IntPtr self;
@ -113,28 +112,28 @@ namespace IEC61850
internal GooseControlBlock(string objectReference, IntPtr connection)
{
self = ClientGooseControlBlock_create (objectReference);
self = ClientGooseControlBlock_create(objectReference);
this.connection = connection;
this.objectReference = objectReference;
}
public string GetObjectReference ()
public string GetObjectReference()
{
return this.objectReference;
return objectReference;
}
/// <summary>
/// Read all GoCB values from the server
/// </summary>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public void GetCBValues ()
public void GetCBValues()
{
int error;
IedConnection_getGoCBValues (connection, out error, objectReference, self);
IedConnection_getGoCBValues(connection, out error, objectReference, self);
if (error != 0)
throw new IedConnectionException ("getGoCBValues service failed", error);
throw new IedConnectionException("getGoCBValues service failed", error);
}
private void
@ -146,7 +145,7 @@ namespace IEC61850
flagDstAddress = false;
}
public void SetCBValues (bool singleRequest)
public void SetCBValues(bool singleRequest)
{
UInt32 parametersMask = 0;
@ -164,82 +163,82 @@ namespace IEC61850
int error;
IedConnection_setGoCBValues (connection, out error, self, parametersMask, singleRequest);
IedConnection_setGoCBValues(connection, out error, self, parametersMask, singleRequest);
resetSendFlags ();
resetSendFlags();
if (error != 0)
throw new IedConnectionException ("setGoCBValues service failed", error);
throw new IedConnectionException("setGoCBValues service failed", error);
}
public void SetCBValues ()
public void SetCBValues()
{
SetCBValues (true);
SetCBValues(true);
}
public bool GetGoEna()
{
return ClientGooseControlBlock_getGoEna (self);
return ClientGooseControlBlock_getGoEna(self);
}
public void SetGoEna(bool value)
{
ClientGooseControlBlock_setGoEna (self, value);
ClientGooseControlBlock_setGoEna(self, value);
flagGoEna = true;
}
public string GetGoID()
{
IntPtr goIdRef = ClientGooseControlBlock_getGoID (self);
IntPtr goIdRef = ClientGooseControlBlock_getGoID(self);
return Marshal.PtrToStringAnsi (goIdRef);
return Marshal.PtrToStringAnsi(goIdRef);
}
public void SetGoID (string goID)
public void SetGoID(string goID)
{
ClientGooseControlBlock_setGoID (self, goID);
ClientGooseControlBlock_setGoID(self, goID);
flagGoID = true;
}
public string GetDatSet()
{
IntPtr datSetRef = ClientGooseControlBlock_getDatSet (self);
IntPtr datSetRef = ClientGooseControlBlock_getDatSet(self);
return Marshal.PtrToStringAnsi (datSetRef);
return Marshal.PtrToStringAnsi(datSetRef);
}
public void SetDataSet(string datSet)
{
ClientGooseControlBlock_setDatSet (self, datSet);
ClientGooseControlBlock_setDatSet(self, datSet);
flagDatSet = true;
}
public UInt32 GetConfRev()
{
return ClientGooseControlBlock_getConfRev (self);
return ClientGooseControlBlock_getConfRev(self);
}
public bool GetNdsComm()
{
return ClientGooseControlBlock_getNdsComm (self);
return ClientGooseControlBlock_getNdsComm(self);
}
public UInt32 GetMinTime()
{
return ClientGooseControlBlock_getMinTime (self);
return ClientGooseControlBlock_getMinTime(self);
}
public UInt32 GetMaxTime()
{
return ClientGooseControlBlock_getMaxTime (self);
return ClientGooseControlBlock_getMaxTime(self);
}
public bool GetFixedOffs()
{
return ClientGooseControlBlock_getFixedOffs (self);
return ClientGooseControlBlock_getFixedOffs(self);
}
public PhyComAddress GetDstAddress()
@ -265,23 +264,24 @@ namespace IEC61850
public void SetDstAddress(PhyComAddress value)
{
ClientGooseControlBlock_setDstAddress (self, value);
ClientGooseControlBlock_setDstAddress(self, value);
flagDstAddress = true;
}
public void Dispose()
{
if (isDisposed == false) {
if (isDisposed == false)
{
isDisposed = true;
ClientGooseControlBlock_destroy (self);
ClientGooseControlBlock_destroy(self);
self = IntPtr.Zero;
}
}
~GooseControlBlock()
{
Dispose ();
Dispose();
}
}

@ -1,7 +1,7 @@
/*
* GooseSubscriber.cs
*
* Copyright 2017 Michael Zillgith
* Copyright 2017-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,10 +21,10 @@
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850
{
@ -37,12 +37,12 @@ namespace IEC61850
/// <summary>
/// GOOSE listener.
/// </summary>
public delegate void GooseListener (GooseSubscriber report, object parameter);
public delegate void GooseListener(GooseSubscriber report, object parameter);
public class GooseReceiver : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseReceiver_create ();
private static extern IntPtr GooseReceiver_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_addSubscriber(IntPtr self, IntPtr subscriber);
@ -58,7 +58,7 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseReceiver_isRunning (IntPtr self);
private static extern bool GooseReceiver_isRunning(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_destroy(IntPtr self);
@ -74,12 +74,12 @@ namespace IEC61850
public GooseReceiver()
{
self = GooseReceiver_create ();
self = GooseReceiver_create();
}
public void SetInterfaceId(string interfaceId)
{
GooseReceiver_setInterfaceId (self, interfaceId);
GooseReceiver_setInterfaceId(self, interfaceId);
}
/// <summary>
@ -109,31 +109,32 @@ namespace IEC61850
public void Start()
{
GooseReceiver_start (self);
GooseReceiver_start(self);
}
public void Stop()
{
GooseReceiver_stop (self);
GooseReceiver_stop(self);
}
public bool IsRunning()
{
return GooseReceiver_isRunning (self);
return GooseReceiver_isRunning(self);
}
public void Dispose()
{
if (isDisposed == false) {
if (isDisposed == false)
{
isDisposed = true;
GooseReceiver_destroy (self);
GooseReceiver_destroy(self);
self = IntPtr.Zero;
}
}
~GooseReceiver()
{
Dispose ();
Dispose();
}
}
@ -149,40 +150,40 @@ namespace IEC61850
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalGooseListener (IntPtr subscriber, IntPtr parameter);
private delegate void InternalGooseListener(IntPtr subscriber, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_create (string goCbRef, IntPtr dataSetValue);
private static extern IntPtr GooseSubscriber_create(string goCbRef, IntPtr dataSetValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseSubscriber_setAppId(IntPtr self, UInt16 appId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseSubscriber_isValid (IntPtr self);
private static extern bool GooseSubscriber_isValid(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getStNum (IntPtr self);
private static extern UInt32 GooseSubscriber_getStNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getSqNum (IntPtr self);
private static extern UInt32 GooseSubscriber_getSqNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseSubscriber_isTest (IntPtr self);
private static extern bool GooseSubscriber_isTest(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getConfRev (IntPtr self);
private static extern UInt32 GooseSubscriber_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseSubscriber_needsCommission (IntPtr self);
private static extern bool GooseSubscriber_needsCommission(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getTimeAllowedToLive (IntPtr self);
private static extern UInt32 GooseSubscriber_getTimeAllowedToLive(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt64 GooseSubscriber_getTimestamp (IntPtr self);
private static extern UInt64 GooseSubscriber_getTimestamp(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getDataSetValues(IntPtr self);
@ -191,7 +192,7 @@ namespace IEC61850
private static extern void GooseSubscriber_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseSubscriber_setListener (IntPtr self, InternalGooseListener listener, IntPtr parameter);
private static extern void GooseSubscriber_setListener(IntPtr self, InternalGooseListener listener, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getGoId(IntPtr self);
@ -214,15 +215,18 @@ namespace IEC61850
private event InternalGooseListener internalListener = null;
private void internalGooseListener (IntPtr subscriber, IntPtr parameter)
private void internalGooseListener(IntPtr subscriber, IntPtr parameter)
{
try
{
try {
if (listener != null) {
if (listener != null)
{
listener(this, listenerParameter);
}
} catch (Exception e)
}
catch (Exception e)
{
// older versions of mono 2.10 (for linux?) cause this exception
Console.WriteLine(e.Message);
@ -231,28 +235,29 @@ namespace IEC61850
public GooseSubscriber(string goCbRef)
{
self = GooseSubscriber_create (goCbRef, IntPtr.Zero);
self = GooseSubscriber_create(goCbRef, IntPtr.Zero);
}
public void SetAppId(UInt16 appId)
{
GooseSubscriber_setAppId (self, appId);
GooseSubscriber_setAppId(self, appId);
}
public bool IsValid ()
public bool IsValid()
{
return GooseSubscriber_isValid (self);
return GooseSubscriber_isValid(self);
}
public void SetListener(GooseListener listener, object parameter)
{
this.listener = listener;
this.listenerParameter = parameter;
listenerParameter = parameter;
if (internalListener == null) {
internalListener = new InternalGooseListener (internalGooseListener);
if (internalListener == null)
{
internalListener = new InternalGooseListener(internalGooseListener);
GooseSubscriber_setListener (self, internalListener, IntPtr.Zero);
GooseSubscriber_setListener(self, internalListener, IntPtr.Zero);
}
}
@ -273,46 +278,46 @@ namespace IEC61850
public UInt32 GetStNum()
{
return GooseSubscriber_getStNum (self);
return GooseSubscriber_getStNum(self);
}
public UInt32 GetSqNum()
{
return GooseSubscriber_getSqNum (self);
return GooseSubscriber_getSqNum(self);
}
public bool IsTest()
{
return GooseSubscriber_isTest (self);
return GooseSubscriber_isTest(self);
}
public UInt32 GetConfRev()
{
return GooseSubscriber_getConfRev (self);
return GooseSubscriber_getConfRev(self);
}
public bool NeedsCommission()
{
return GooseSubscriber_needsCommission (self);
return GooseSubscriber_needsCommission(self);
}
public UInt32 GetTimeAllowedToLive()
{
return GooseSubscriber_getTimeAllowedToLive (self);
return GooseSubscriber_getTimeAllowedToLive(self);
}
public UInt64 GetTimestamp ()
public UInt64 GetTimestamp()
{
return GooseSubscriber_getTimestamp (self);
return GooseSubscriber_getTimestamp(self);
}
public DateTimeOffset GetTimestampsDateTimeOffset ()
public DateTimeOffset GetTimestampsDateTimeOffset()
{
UInt64 entryTime = GetTimestamp ();
UInt64 entryTime = GetTimestamp();
DateTimeOffset retVal = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
DateTimeOffset retVal = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
return retVal.AddMilliseconds (entryTime);
return retVal.AddMilliseconds(entryTime);
}
/// <summary>
@ -325,9 +330,9 @@ namespace IEC61850
/// <returns>The data set values.</returns>
public MmsValue GetDataSetValues()
{
IntPtr mmsValueRef = GooseSubscriber_getDataSetValues (self);
IntPtr mmsValueRef = GooseSubscriber_getDataSetValues(self);
return (new MmsValue (mmsValueRef));
return (new MmsValue(mmsValueRef));
}
/// <summary>
@ -342,11 +347,12 @@ namespace IEC61850
/// </remarks>
public void Dispose()
{
if (isDisposed == false) {
if (isDisposed == false)
{
isDisposed = true;
if (attachedToReceiver == false)
GooseSubscriber_destroy (self);
GooseSubscriber_destroy(self);
self = IntPtr.Zero;
}

@ -1,7 +1,7 @@
/*
* IEC61850ClientAPI.cs
*
* Copyright 2014-2023 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,14 +20,11 @@
*
* 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 IEC61850.Common;
using IEC61850.TLS;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
@ -62,11 +59,11 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void MmsServerIdentity_destroy(IntPtr self);
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
private static extern void MmsConnection_setLocalDetail (IntPtr self, Int32 localDetail);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void MmsConnection_setLocalDetail(IntPtr self, Int32 localDetail);
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
private static extern Int32 MmsConnection_getLocalDetail (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 MmsConnection_getLocalDetail(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 MmsConnection_setRequestTimeout(IntPtr self, UInt32 timeoutInMs);
@ -106,7 +103,7 @@ namespace IEC61850
self = mmsConnection;
}
~MmsConnection ()
~MmsConnection()
{
if (selfDestroy)
if (self != IntPtr.Zero)
@ -343,7 +340,7 @@ namespace IEC61850
}
}
~MmsJournalEntry ()
~MmsJournalEntry()
{
Dispose();
}
@ -356,7 +353,7 @@ namespace IEC61850
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
/// <param name="rcb">the report control block instance</param>
public delegate void GetRCBValuesHandler(UInt32 invokeId,object parameter,IedClientError err,ReportControlBlock rcb);
public delegate void GetRCBValuesHandler(UInt32 invokeId, object parameter, IedClientError err, ReportControlBlock rcb);
/// <summary>
/// Asynchonous service handler for the set RCB values service
@ -365,7 +362,7 @@ namespace IEC61850
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
/// <param name="rcb">the report control block instance</param>
public delegate void SetRCBValuesHandler(UInt32 invokeId,object parameter,IedClientError err,ReportControlBlock rcb);
public delegate void SetRCBValuesHandler(UInt32 invokeId, object parameter, IedClientError err, ReportControlBlock rcb);
/// <summary>
/// Generic asynchonous service handler - used by simple services that have only success or error result
@ -373,7 +370,7 @@ namespace IEC61850
/// <param name="invokeId">The invoke ID of the request triggering this callback</param>
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
public delegate void GenericServiceHandler(UInt32 invokeId,object parameter,IedClientError err);
public delegate void GenericServiceHandler(UInt32 invokeId, object parameter, IedClientError err);
/// <summary>
/// This class acts as the entry point for the IEC 61850 client API. It represents a single
@ -483,7 +480,7 @@ namespace IEC61850
static extern IntPtr IedConnection_getVariableSpecification(IntPtr self, out int error, string objectReference, int fc);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalConnectionClosedHandler(IntPtr parameter,IntPtr Iedconnection);
private delegate void InternalConnectionClosedHandler(IntPtr parameter, IntPtr Iedconnection);
/// <summary>
/// Called when the connection is closed
@ -552,7 +549,7 @@ namespace IEC61850
static extern int IedConnection_getState(IntPtr connection);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalStateChangedHandler(IntPtr parameter,IntPtr iedConnection,int newState);
private delegate void InternalStateChangedHandler(IntPtr parameter, IntPtr iedConnection, int newState);
/// <summary>
/// Called when there is a change in the connection state
@ -582,7 +579,7 @@ namespace IEC61850
private static extern void IedConnection_releaseAsync(IntPtr self, out int error);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_ReadObjectHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr value);
private delegate void IedConnection_ReadObjectHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
@ -590,7 +587,7 @@ namespace IEC61850
IedConnection_ReadObjectHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_WriteObjectHandler(UInt32 invokeId,IntPtr parameter,int err);
private delegate void IedConnection_WriteObjectHandler(UInt32 invokeId, IntPtr parameter, int err);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
@ -598,7 +595,7 @@ namespace IEC61850
IntPtr value, IedConnection_WriteObjectHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_GetNameListHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr nameList,[MarshalAs(UnmanagedType.I1)] bool moreFollows);
private delegate void IedConnection_GetNameListHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr nameList, [MarshalAs(UnmanagedType.I1)] bool moreFollows);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
@ -616,7 +613,7 @@ namespace IEC61850
IedConnection_GetNameListHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_QueryLogHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr journalEntries,[MarshalAs(UnmanagedType.I1)] bool moreFollows);
private delegate void IedConnection_QueryLogHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr journalEntries, [MarshalAs(UnmanagedType.I1)] bool moreFollows);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
@ -629,7 +626,7 @@ namespace IEC61850
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);
private delegate void IedConnection_GetVariableSpecificationHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr spec);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
@ -663,7 +660,7 @@ namespace IEC61850
IedConnection_GetDataSetDirectoryHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_GetRCBValuesHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr rcb);
private delegate void IedConnection_GetRCBValuesHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr rcb);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
@ -671,7 +668,7 @@ namespace IEC61850
IedConnection_GetRCBValuesHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_GenericServiceHandler(UInt32 invokeId,IntPtr parameter,int err);
private delegate void IedConnection_GenericServiceHandler(UInt32 invokeId, IntPtr parameter, int err);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
@ -759,7 +756,7 @@ namespace IEC61850
}
}
~IedConnection ()
~IedConnection()
{
Dispose();
}
@ -1632,7 +1629,7 @@ namespace IEC61850
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool InternalIedClientGetFileHandler(IntPtr parameter,IntPtr buffer,UInt32 bytesRead);
private delegate bool InternalIedClientGetFileHandler(IntPtr parameter, IntPtr buffer, UInt32 bytesRead);
private bool iedClientGetFileHandler(IntPtr parameter, IntPtr buffer, UInt32 bytesRead)
{
@ -1658,7 +1655,7 @@ namespace IEC61850
static extern void IedConnection_setFilestoreBasepath(IntPtr self, string fileName);
public delegate bool GetFileHandler(object parameter,byte[] data);
public delegate bool GetFileHandler(object parameter, byte[] data);
private class GetFileCallback
{
@ -2338,7 +2335,7 @@ namespace IEC61850
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
/// <param name="value">The read result value or null in case of an error</param>
public delegate void ReadValueHandler(UInt32 invokeId,object parameter,IedClientError err,MmsValue value);
public delegate void ReadValueHandler(UInt32 invokeId, object parameter, IedClientError err, MmsValue value);
private IedConnection_ReadObjectHandler internalReadObjectHandler = null;
@ -2417,7 +2414,7 @@ namespace IEC61850
handler(invokeId, handlerParameter, clientError, varSpec);
}
public delegate void GetVariableSpecifcationHandler(UInt32 invokeId,object parameter,IedClientError err,MmsVariableSpecification spec);
public delegate void GetVariableSpecifcationHandler(UInt32 invokeId, object parameter, IedClientError err, MmsVariableSpecification spec);
/// <summary>Read the variable specification (type description of a DA or FCDO</summary>
/// <param name="objectReference">The object reference of a DA or FCDO.</param>
@ -2473,7 +2470,7 @@ namespace IEC61850
handler(invokeId, handlerParameter, clientError, dataSet);
}
public delegate void ReadDataSetHandler(UInt32 invokeId,object parameter,IedClientError err,DataSet dataSet);
public delegate void ReadDataSetHandler(UInt32 invokeId, object parameter, IedClientError err, DataSet dataSet);
/// <summary>
/// Read the values of a data set (GetDataSetValues service) - asynchronous version
@ -2521,7 +2518,7 @@ namespace IEC61850
/// <param name="invokeId">The invoke ID of the reqeust triggering this callback</param>
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
public delegate void WriteValueHandler(UInt32 invokeId,object parameter,IedClientError err);
public delegate void WriteValueHandler(UInt32 invokeId, object parameter, IedClientError err);
private IedConnection_WriteObjectHandler internalWriteObjectHandler = null;
@ -2563,7 +2560,7 @@ namespace IEC61850
return invokeId;
}
public delegate void GetNameListHandler(UInt32 invokeId,object parameter,IedClientError err,List<string> nameList,bool moreFollows);
public delegate void GetNameListHandler(UInt32 invokeId, object parameter, IedClientError err, List<string> nameList, bool moreFollows);
private IedConnection_GetNameListHandler internalGetNameListHandler = null;
@ -2692,7 +2689,7 @@ namespace IEC61850
return invokeId;
}
public delegate void QueryLogHandler(UInt32 invokeId,object parameter,IedClientError err,List<MmsJournalEntry> journalEntries,bool moreFollows);
public delegate void QueryLogHandler(UInt32 invokeId, object parameter, IedClientError err, List<MmsJournalEntry> journalEntries, bool moreFollows);
private IedConnection_QueryLogHandler internalQueryLogHandler = null;
@ -2936,17 +2933,17 @@ namespace IEC61850
public IedConnectionException(string message)
: base(message)
{
this.errorCode = 0;
errorCode = 0;
}
public int GetErrorCode()
{
return this.errorCode;
return errorCode;
}
public IedClientError GetIedClientError()
{
return (IedClientError)this.errorCode;
return (IedClientError)errorCode;
}
}

@ -1,7 +1,7 @@
/*
* IEC61850CommonAPI.cs
*
* Copyright 2014-2024 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -47,7 +47,7 @@ namespace IEC61850
/// <returns>The version string in format MAJOR.MINOR.PATCH</returns>
public static string GetVersionString()
{
return Marshal.PtrToStringAnsi (LibIEC61850_getVersionString ());
return Marshal.PtrToStringAnsi(LibIEC61850_getVersionString());
}
/// <summary>
@ -62,8 +62,8 @@ namespace IEC61850
ulong seconds = msTime / 1000;
ulong millies = msTime % 1000;
dateTime.AddSeconds ((double) seconds);
dateTime.AddMilliseconds((double) millies);
dateTime.AddSeconds(seconds);
dateTime.AddMilliseconds(millies);
return dateTime;
}
@ -75,7 +75,7 @@ namespace IEC61850
/// <param name="msTime">The DateTime object to convert</param>
public static ulong DateTimeToMsTimestamp(DateTime dateTime)
{
return (ulong) (dateTime.ToUniversalTime ().Subtract (new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds);
return (ulong)(dateTime.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds);
}
}
@ -86,14 +86,15 @@ namespace IEC61850
public UInt16 vlanId;
public UInt16 appId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] dstAddress = new byte[6];
}
/// <summary>
/// MMS data access error for MmsValue type MMS_DATA_ACCESS_ERROR
/// </summary>
public enum MmsDataAccessError {
public enum MmsDataAccessError
{
NO_RESPONSE = -2, /* for server internal purposes only! */
SUCCESS = -1,
OBJECT_INVALIDATED = 0,
@ -112,7 +113,8 @@ namespace IEC61850
}
[Flags]
public enum TriggerOptions {
public enum TriggerOptions
{
NONE = 0,
/** send report when value of data changed */
DATA_CHANGED = 1,
@ -131,7 +133,8 @@ namespace IEC61850
/// <summary>
/// SmpMod values
/// </summary>
public enum SmpMod {
public enum SmpMod
{
SAMPLES_PER_PERIOD = 0,
SAMPLES_PER_SECOND = 1,
SECONDS_PER_SAMPLE = 2
@ -141,7 +144,8 @@ namespace IEC61850
/// Values for Sampled Values (SV) OptFlds
/// </summary>
[Flags]
public enum SVOptions {
public enum SVOptions
{
NONE = 0,
REFRESH_TIME = 1,
SAMPLE_SYNC = 2,
@ -152,7 +156,8 @@ namespace IEC61850
}
[Flags]
public enum ReportOptions {
public enum ReportOptions
{
NONE = 0,
SEQ_NUM = 1,
TIME_STAMP = 2,
@ -197,30 +202,30 @@ namespace IEC61850
public ushort Value => value;
public override string ToString ()
public override string ToString()
{
return GetValidity ().ToString ();
return GetValidity().ToString();
}
public Quality (int bitStringValue)
public Quality(int bitStringValue)
{
value = (UInt16)bitStringValue;
}
public Quality ()
public Quality()
{
value = 0;
}
public Validity GetValidity ()
public Validity GetValidity()
{
int qualityVal = value & 0x3;
return (Validity)qualityVal;
}
public void SetValidity (Validity validity)
public void SetValidity(Validity validity)
{
value = (UInt16)(value & 0xfffc);
@ -229,139 +234,151 @@ namespace IEC61850
public Validity Validity
{
get {return GetValidity ();}
set { SetValidity (value); }
get { return GetValidity(); }
set { SetValidity(value); }
}
public bool Overflow
{
get { return ((this.value & QUALITY_DETAIL_OVERFLOW) != 0);}
set {
get { return ((value & QUALITY_DETAIL_OVERFLOW) != 0); }
set
{
if (value)
this.value |= QUALITY_DETAIL_OVERFLOW;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_OVERFLOW));
this.value = (ushort)(this.value & (~QUALITY_DETAIL_OVERFLOW));
}
}
public bool OutOfRange
{
get { return ((this.value & QUALITY_DETAIL_OUT_OF_RANGE) != 0);}
set {
get { return ((value & QUALITY_DETAIL_OUT_OF_RANGE) != 0); }
set
{
if (value)
this.value |= QUALITY_DETAIL_OUT_OF_RANGE;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_OUT_OF_RANGE));
this.value = (ushort)(this.value & (~QUALITY_DETAIL_OUT_OF_RANGE));
}
}
public bool BadReference
{
get { return ((this.value & QUALITY_DETAIL_BAD_REFERENCE) != 0);}
set {
get { return ((value & QUALITY_DETAIL_BAD_REFERENCE) != 0); }
set
{
if (value)
this.value |= QUALITY_DETAIL_BAD_REFERENCE;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_BAD_REFERENCE));
this.value = (ushort)(this.value & (~QUALITY_DETAIL_BAD_REFERENCE));
}
}
public bool Oscillatory
{
get { return ((this.value & QUALITY_DETAIL_OSCILLATORY) != 0);}
set {
get { return ((value & QUALITY_DETAIL_OSCILLATORY) != 0); }
set
{
if (value)
this.value |= QUALITY_DETAIL_OSCILLATORY;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_OSCILLATORY));
this.value = (ushort)(this.value & (~QUALITY_DETAIL_OSCILLATORY));
}
}
public bool Failure
{
get { return ((this.value & QUALITY_DETAIL_FAILURE) != 0);}
set {
get { return ((value & QUALITY_DETAIL_FAILURE) != 0); }
set
{
if (value)
this.value |= QUALITY_DETAIL_FAILURE;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_FAILURE));
this.value = (ushort)(this.value & (~QUALITY_DETAIL_FAILURE));
}
}
public bool OldData
{
get { return ((this.value & QUALITY_DETAIL_OLD_DATA) != 0);}
set {
get { return ((value & QUALITY_DETAIL_OLD_DATA) != 0); }
set
{
if (value)
this.value |= QUALITY_DETAIL_OLD_DATA;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_OLD_DATA));
this.value = (ushort)(this.value & (~QUALITY_DETAIL_OLD_DATA));
}
}
public bool Inconsistent
{
get { return ((this.value & QUALITY_DETAIL_INCONSISTENT) != 0);}
set {
get { return ((value & QUALITY_DETAIL_INCONSISTENT) != 0); }
set
{
if (value)
this.value |= QUALITY_DETAIL_INCONSISTENT;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_INCONSISTENT));
this.value = (ushort)(this.value & (~QUALITY_DETAIL_INCONSISTENT));
}
}
public bool Inaccurate
{
get { return ((this.value & QUALITY_DETAIL_INACCURATE) != 0);}
set {
get { return ((value & QUALITY_DETAIL_INACCURATE) != 0); }
set
{
if (value)
this.value |= QUALITY_DETAIL_INACCURATE;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_INACCURATE));
this.value = (ushort)(this.value & (~QUALITY_DETAIL_INACCURATE));
}
}
public bool Substituted
{
get { return ((this.value & QUALITY_SOURCE_SUBSTITUTED) != 0);}
set {
get { return ((value & QUALITY_SOURCE_SUBSTITUTED) != 0); }
set
{
if (value)
this.value |= QUALITY_SOURCE_SUBSTITUTED;
else
this.value = (ushort) ((int) this.value & (~QUALITY_SOURCE_SUBSTITUTED));
this.value = (ushort)(this.value & (~QUALITY_SOURCE_SUBSTITUTED));
}
}
public bool Test
{
get { return ((this.value & QUALITY_TEST) != 0);}
set {
get { return ((value & QUALITY_TEST) != 0); }
set
{
if (value)
this.value |= QUALITY_TEST;
else
this.value = (ushort) ((int) this.value & (~QUALITY_TEST));
this.value = (ushort)(this.value & (~QUALITY_TEST));
}
}
public bool OperatorBlocked
{
get { return ((this.value & QUALITY_OPERATOR_BLOCKED) != 0);}
set {
get { return ((value & QUALITY_OPERATOR_BLOCKED) != 0); }
set
{
if (value)
this.value |= QUALITY_OPERATOR_BLOCKED;
else
this.value = (ushort) ((int) this.value & (~QUALITY_OPERATOR_BLOCKED));
this.value = (ushort)(this.value & (~QUALITY_OPERATOR_BLOCKED));
}
}
public bool Derived
{
get { return ((this.value & QUALITY_DERIVED) != 0); }
set {
get { return ((value & QUALITY_DERIVED) != 0); }
set
{
if (value)
this.value |= QUALITY_DERIVED;
else
this.value = (ushort) ((int) this.value & (~QUALITY_DERIVED));
this.value = (ushort)(this.value & (~QUALITY_DERIVED));
}
}
}
@ -372,59 +389,59 @@ namespace IEC61850
public class Timestamp
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr Timestamp_create ();
static extern IntPtr Timestamp_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr Timestamp_createFromByteArray(byte[] byteArry);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_destroy (IntPtr self);
static extern void Timestamp_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_clearFlags (IntPtr self);
static extern void Timestamp_clearFlags(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool Timestamp_isLeapSecondKnown (IntPtr self);
static extern bool Timestamp_isLeapSecondKnown(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setLeapSecondKnown (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
static extern void Timestamp_setLeapSecondKnown(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool Timestamp_hasClockFailure (IntPtr self);
static extern bool Timestamp_hasClockFailure(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setClockFailure (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
static extern void Timestamp_setClockFailure(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool Timestamp_isClockNotSynchronized (IntPtr self);
static extern bool Timestamp_isClockNotSynchronized(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setClockNotSynchronized (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
static extern void Timestamp_setClockNotSynchronized(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int Timestamp_getSubsecondPrecision (IntPtr self);
static extern int Timestamp_getSubsecondPrecision(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setSubsecondPrecision(IntPtr self, int subsecondPrecision);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setTimeInSeconds (IntPtr self, UInt32 secondsSinceEpoch);
static extern void Timestamp_setTimeInSeconds(IntPtr self, UInt32 secondsSinceEpoch);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setTimeInMilliseconds (IntPtr self, UInt64 millisSinceEpoch);
static extern void Timestamp_setTimeInMilliseconds(IntPtr self, UInt64 millisSinceEpoch);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 Timestamp_getTimeInSeconds (IntPtr self);
static extern UInt32 Timestamp_getTimeInSeconds(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt64 Timestamp_getTimeInMs (IntPtr self);
static extern UInt64 Timestamp_getTimeInMs(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setByMmsUtcTime (IntPtr self, IntPtr mmsValue);
static extern void Timestamp_setByMmsUtcTime(IntPtr self, IntPtr mmsValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 Timestamp_getFractionOfSecondPart(IntPtr self);
@ -440,18 +457,18 @@ namespace IEC61850
internal Timestamp(IntPtr timestampRef, bool selfAllocated)
{
this.self = timestampRef;
this.responsibleForDeletion = selfAllocated;
self = timestampRef;
responsibleForDeletion = selfAllocated;
}
public Timestamp (DateTime timestamp) : this ()
public Timestamp(DateTime timestamp) : this()
{
SetDateTime (timestamp);
SetDateTime(timestamp);
}
public Timestamp (MmsValue mmsUtcTime) : this()
public Timestamp(MmsValue mmsUtcTime) : this()
{
SetByMmsUtcTime (mmsUtcTime);
SetByMmsUtcTime(mmsUtcTime);
}
/// <summary>
@ -459,7 +476,7 @@ namespace IEC61850
/// </summary>
public Timestamp()
{
self = Timestamp_create ();
self = Timestamp_create();
LeapSecondKnown = true;
responsibleForDeletion = true;
}
@ -469,9 +486,9 @@ namespace IEC61850
/// </summary>
public Timestamp(Timestamp other) : this()
{
SetTimeInSeconds (other.GetTimeInSeconds ());
SetSubsecondPrecision (other.GetSubsecondPrecision ());
SetFractionOfSecondPart (other.GetFractionOfSecondPart ());
SetTimeInSeconds(other.GetTimeInSeconds());
SetSubsecondPrecision(other.GetSubsecondPrecision());
SetFractionOfSecondPart(other.GetFractionOfSecondPart());
SetLeapSecondKnow(other.IsLeapSecondKnown());
SetClockFailure(other.HasClockFailure());
SetClockNotSynchronized(other.IsClockNotSynchronized());
@ -479,19 +496,19 @@ namespace IEC61850
public Timestamp(byte[] value)
{
self = Timestamp_createFromByteArray (value);
self = Timestamp_createFromByteArray(value);
responsibleForDeletion = true;
}
~Timestamp ()
~Timestamp()
{
if (responsibleForDeletion)
Timestamp_destroy (self);
Timestamp_destroy(self);
}
public void ClearFlags()
{
Timestamp_clearFlags (self);
Timestamp_clearFlags(self);
}
public void SetDateTime(DateTime timestamp)
@ -502,104 +519,115 @@ namespace IEC61850
TimeSpan timeDiff = timestampUTC - epoch;
ulong timeVal = Convert.ToUInt64(timeDiff.TotalMilliseconds);
SetTimeInMilliseconds (timeVal);
SetTimeInMilliseconds(timeVal);
}
public bool LeapSecondKnown {
get { return IsLeapSecondKnown ();}
set { SetLeapSecondKnow (value);}
public bool LeapSecondKnown
{
get { return IsLeapSecondKnown(); }
set { SetLeapSecondKnow(value); }
}
public bool IsLeapSecondKnown()
{
return Timestamp_isLeapSecondKnown (self);
return Timestamp_isLeapSecondKnown(self);
}
public void SetLeapSecondKnow(bool value)
{
Timestamp_setLeapSecondKnown (self, value);
Timestamp_setLeapSecondKnown(self, value);
}
public bool ClockFailure {
get { return HasClockFailure ();}
set { SetClockFailure (value);}
public bool ClockFailure
{
get { return HasClockFailure(); }
set { SetClockFailure(value); }
}
public bool HasClockFailure()
{
return Timestamp_hasClockFailure (self);
return Timestamp_hasClockFailure(self);
}
public void SetClockFailure(bool value)
{
Timestamp_setClockFailure (self, value);
Timestamp_setClockFailure(self, value);
}
public bool ClockNotSynchronized {
get { return IsClockNotSynchronized (); }
set { SetClockNotSynchronized (value); }
public bool ClockNotSynchronized
{
get { return IsClockNotSynchronized(); }
set { SetClockNotSynchronized(value); }
}
public bool IsClockNotSynchronized() {
public bool IsClockNotSynchronized()
{
return Timestamp_isClockNotSynchronized(self);
}
public void SetClockNotSynchronized(bool value) {
Timestamp_setClockNotSynchronized (self, value);
public void SetClockNotSynchronized(bool value)
{
Timestamp_setClockNotSynchronized(self, value);
}
public int SubsecondPrecision {
get { return GetSubsecondPrecision (); }
set { SetSubsecondPrecision (value); }
public int SubsecondPrecision
{
get { return GetSubsecondPrecision(); }
set { SetSubsecondPrecision(value); }
}
public int GetSubsecondPrecision() {
return Timestamp_getSubsecondPrecision (self);
public int GetSubsecondPrecision()
{
return Timestamp_getSubsecondPrecision(self);
}
public void SetSubsecondPrecision(int subsecondPrecision) {
Timestamp_setSubsecondPrecision (self, subsecondPrecision);
public void SetSubsecondPrecision(int subsecondPrecision)
{
Timestamp_setSubsecondPrecision(self, subsecondPrecision);
}
public UInt32 TimeInSeconds {
get { return GetTimeInSeconds (); }
set { SetTimeInSeconds (value); }
public UInt32 TimeInSeconds
{
get { return GetTimeInSeconds(); }
set { SetTimeInSeconds(value); }
}
public UInt32 GetTimeInSeconds()
{
return Timestamp_getTimeInSeconds (self);
return Timestamp_getTimeInSeconds(self);
}
public void SetTimeInSeconds(UInt32 secondsSinceEpoch)
{
Timestamp_setTimeInSeconds (self, secondsSinceEpoch);
Timestamp_setTimeInSeconds(self, secondsSinceEpoch);
}
public UInt64 TimeInMilliseconds {
get { return GetTimeInMilliseconds (); }
set { SetTimeInMilliseconds (value); }
public UInt64 TimeInMilliseconds
{
get { return GetTimeInMilliseconds(); }
set { SetTimeInMilliseconds(value); }
}
public UInt64 GetTimeInMilliseconds()
{
return Timestamp_getTimeInMs (self);
return Timestamp_getTimeInMs(self);
}
public void SetTimeInMilliseconds(UInt64 millisSinceEpoch) {
Timestamp_setTimeInMilliseconds (self, millisSinceEpoch);
public void SetTimeInMilliseconds(UInt64 millisSinceEpoch)
{
Timestamp_setTimeInMilliseconds(self, millisSinceEpoch);
}
public void SetByMmsUtcTime(MmsValue mmsValue)
{
Timestamp_setByMmsUtcTime (self, mmsValue.valueReference);
Timestamp_setByMmsUtcTime(self, mmsValue.valueReference);
}
public DateTime AsDateTime()
{
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime retVal = epoch.AddMilliseconds ((double) GetTimeInMilliseconds ());
DateTime retVal = epoch.AddMilliseconds(GetTimeInMilliseconds());
return retVal;
}
@ -695,7 +723,8 @@ namespace IEC61850
/// Definition for LastAppError error type for control models
/// Used in LastApplError and CommandTermination messages.
/// </summary>
public enum ControlLastApplError {
public enum ControlLastApplError
{
NO_ERROR = 0,
UNKNOWN = 1,
TIMEOUT_TEST = 2,
@ -706,7 +735,8 @@ namespace IEC61850
/// AddCause - additional cause information for control model errors
/// Used in LastApplError and CommandTermination messages.
/// </summary>
public enum ControlAddCause {
public enum ControlAddCause
{
ADD_CAUSE_UNKNOWN = 0,
ADD_CAUSE_NOT_SUPPORTED = 1,
ADD_CAUSE_BLOCKED_BY_SWITCHING_HIERARCHY = 2,
@ -740,7 +770,8 @@ namespace IEC61850
/// <summary>
/// Object reference. Helper function to handle object reference strings.
/// </summary>
public static class ObjectReference {
public static class ObjectReference
{
/// <summary>
/// Get the name part of an object reference with appended FC
@ -751,7 +782,7 @@ namespace IEC61850
/// <param name='objectReferenceWithFc'>
/// Object reference with appended fc.
/// </param>
public static string getElementName (string objectReferenceWithFc)
public static string getElementName(string objectReferenceWithFc)
{
int fcPartStartIndex = objectReferenceWithFc.IndexOf('[');
@ -770,20 +801,20 @@ namespace IEC61850
/// <param name='objectReferenceWithFc'>
/// Object reference with FC.
/// </param>
public static FunctionalConstraint getFC (string objectReferenceWithFc)
public static FunctionalConstraint getFC(string objectReferenceWithFc)
{
int fcPartStartIndex = objectReferenceWithFc.IndexOf('[');
if (fcPartStartIndex == -1)
return FunctionalConstraint.NONE;
string fcString = objectReferenceWithFc.Substring(fcPartStartIndex + 1 , 2);
string fcString = objectReferenceWithFc.Substring(fcPartStartIndex + 1, 2);
try
{
return (FunctionalConstraint) Enum.Parse(typeof(FunctionalConstraint), fcString);
return (FunctionalConstraint)Enum.Parse(typeof(FunctionalConstraint), fcString);
}
catch(ArgumentException)
catch (ArgumentException)
{
return FunctionalConstraint.NONE;
}

@ -22,9 +22,7 @@
*/
using IEC61850.Server;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
@ -45,7 +43,7 @@ namespace IEC61850
internal IntPtr Self { get => self; }
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr SVControlBlock_create(string name, IntPtr parent, string svID,string dataSet, UInt32 confRev, uint smpMod,
static extern IntPtr SVControlBlock_create(string name, IntPtr parent, string svID, string dataSet, UInt32 confRev, uint smpMod,
UInt16 smpRate, uint optFlds, bool isUnicast);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
@ -67,7 +65,7 @@ namespace IEC61850
public SVControlBlock(string name, IedModel parent, string svID, string dataSet, UInt32 confRev, uint smpMod,
UInt16 smpRate, uint optFlds, bool isUnicast)
{
this.self = SVControlBlock_create(name, parent.self, svID, dataSet, confRev, smpMod, smpRate, optFlds, isUnicast);
self = SVControlBlock_create(name, parent.self, svID, dataSet, confRev, smpMod, smpRate, optFlds, isUnicast);
this.parent = parent;
}

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
/*
* IedServerConfig.cs
*
* Copyright 2018 Michael Zillgith
* Copyright 2018-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,9 +21,9 @@
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850.Server
{

@ -1,7 +1,7 @@
/*
* IsoConnectionParameters.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -29,7 +29,8 @@ namespace IEC61850
namespace Client
{
public enum AcseAuthenticationMechanism {
public enum AcseAuthenticationMechanism
{
/** don't use authentication */
ACSE_AUTH_NONE = 0,
/** use password authentication */
@ -47,7 +48,7 @@ namespace IEC61850
{
public byte size;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public byte[] value;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] value;
}
@ -56,7 +57,7 @@ namespace IEC61850
{
public byte size;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] public byte[] value;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] value;
}
[StructLayout(LayoutKind.Sequential)]
@ -101,12 +102,12 @@ namespace IEC61850
private IntPtr authParameter = IntPtr.Zero;
internal IsoConnectionParameters (IntPtr self)
internal IsoConnectionParameters(IntPtr self)
{
this.self = self;
}
~IsoConnectionParameters ()
~IsoConnectionParameters()
{
if (authParameter != IntPtr.Zero)
AcseAuthenticationParameter_destroy(authParameter);
@ -138,13 +139,13 @@ namespace IEC61850
/// <param name='tSelector'>
/// ISO COTP transport layer address
/// </param>
public void SetRemoteAddresses (byte[] pSelector, byte[] sSelector, byte[] tSelector)
public void SetRemoteAddresses(byte[] pSelector, byte[] sSelector, byte[] tSelector)
{
if (tSelector.Length > 4)
throw new ArgumentOutOfRangeException("tSelector", "maximum size (4) exceeded");
NativeTSelector nativeTSelector;
nativeTSelector.size = (byte) tSelector.Length;
nativeTSelector.size = (byte)tSelector.Length;
nativeTSelector.value = new byte[4];
for (int i = 0; i < tSelector.Length; i++)
@ -154,11 +155,11 @@ namespace IEC61850
throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded");
NativeSSelector nativeSSelector;
nativeSSelector.size = (byte) sSelector.Length;
nativeSSelector.size = (byte)sSelector.Length;
nativeSSelector.value = new byte[16];
for (int i = 0; i < sSelector.Length; i++)
nativeSSelector.value [i] = sSelector [i];
nativeSSelector.value[i] = sSelector[i];
if (pSelector.Length > 16)
throw new ArgumentOutOfRangeException("pSelector", "maximum size (16) exceeded");
@ -182,7 +183,7 @@ namespace IEC61850
/// <param name='aeQualifier'>
/// local AE qualifier.
/// </param>
public void SetLocalApTitle (string apTitle, int aeQualifier)
public void SetLocalApTitle(string apTitle, int aeQualifier)
{
IsoConnectionParameters_setLocalApTitle(self, apTitle, aeQualifier);
}
@ -199,13 +200,13 @@ namespace IEC61850
/// <param name='tSelector'>
/// ISO COTP transport layer address
/// </param>
public void SetLocalAddresses (byte[] pSelector, byte[] sSelector, byte[] tSelector)
public void SetLocalAddresses(byte[] pSelector, byte[] sSelector, byte[] tSelector)
{
if (tSelector.Length > 4)
throw new ArgumentOutOfRangeException("tSelector", "maximum size (4) exceeded");
NativeTSelector nativeTSelector;
nativeTSelector.size = (byte) tSelector.Length;
nativeTSelector.size = (byte)tSelector.Length;
nativeTSelector.value = new byte[4];
for (int i = 0; i < tSelector.Length; i++)
@ -215,11 +216,11 @@ namespace IEC61850
throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded");
NativeSSelector nativeSSelector;
nativeSSelector.size = (byte) sSelector.Length;
nativeSSelector.size = (byte)sSelector.Length;
nativeSSelector.value = new byte[16];
for (int i = 0; i < sSelector.Length; i++)
nativeSSelector.value [i] = sSelector [i];
nativeSSelector.value[i] = sSelector[i];
if (pSelector.Length > 16)
throw new ArgumentOutOfRangeException("pSelector", "maximum size (16) exceeded");
@ -240,12 +241,13 @@ namespace IEC61850
/// <param name='password'>
/// Password that will be used to authenticate the client
/// </param>
public void UsePasswordAuthentication (string password)
public void UsePasswordAuthentication(string password)
{
if (authParameter == IntPtr.Zero)
{
if (authParameter == IntPtr.Zero) {
authParameter = AcseAuthenticationParameter_create ();
AcseAuthenticationParameter_setAuthMechanism (authParameter, (int)AcseAuthenticationMechanism.ACSE_AUTH_PASSWORD);
AcseAuthenticationParameter_setPassword (authParameter, password);
authParameter = AcseAuthenticationParameter_create();
AcseAuthenticationParameter_setAuthMechanism(authParameter, (int)AcseAuthenticationMechanism.ACSE_AUTH_PASSWORD);
AcseAuthenticationParameter_setPassword(authParameter, password);
IsoConnectionParameters_setAcseAuthenticationParameter(self, authParameter);
}
else

@ -1,7 +1,7 @@
/*
* MmsValue.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,11 +21,8 @@
* See COPYING file for the complete license text.
*/
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;
namespace IEC61850
@ -38,29 +35,29 @@ namespace IEC61850
public class MmsValue : IEnumerable, IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_toString (IntPtr self);
static extern IntPtr MmsValue_toString(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern float MmsValue_toFloat (IntPtr self);
static extern float MmsValue_toFloat(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setFloat (IntPtr self, float value);
static extern void MmsValue_setFloat(IntPtr self, float value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern double MmsValue_toDouble (IntPtr self);
static extern double MmsValue_toDouble(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setDouble (IntPtr self, double newFloatValue);
static extern void MmsValue_setDouble(IntPtr self, double newFloatValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool MmsValue_getBoolean (IntPtr self);
static extern bool MmsValue_getBoolean(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setBoolean(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 MmsValue_getBitStringAsInteger (IntPtr self);
static extern UInt32 MmsValue_getBitStringAsInteger(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setBitStringFromInteger(IntPtr self, UInt32 intValue);
@ -82,64 +79,64 @@ namespace IEC61850
static extern bool MmsValue_getBitStringBit(IntPtr self, int bitPos);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern Int32 MmsValue_toInt32 (IntPtr self);
static extern Int32 MmsValue_toInt32(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setInt32(IntPtr self, int value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern Int64 MmsValue_toInt64 (IntPtr self);
static extern Int64 MmsValue_toInt64(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 MmsValue_toUint32 (IntPtr self);
static extern UInt32 MmsValue_toUint32(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsValue_getType (IntPtr self);
static extern int MmsValue_getType(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_delete (IntPtr self);
static extern void MmsValue_delete(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_getElement (IntPtr complexValue, int index);
static extern IntPtr MmsValue_getElement(IntPtr complexValue, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsValue_getArraySize (IntPtr self);
static extern int MmsValue_getArraySize(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern ulong MmsValue_getUtcTimeInMs (IntPtr self);
static extern ulong MmsValue_getUtcTimeInMs(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setUtcTimeMs (IntPtr self, ulong timeval);
static extern void MmsValue_setUtcTimeMs(IntPtr self, ulong timeval);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern ulong MmsValue_getUtcTimeInMsWithUs(IntPtr self, [Out] uint usec);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern byte MmsValue_getUtcTimeQuality (IntPtr self);
static extern byte MmsValue_getUtcTimeQuality(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setUtcTimeQuality (IntPtr self, byte timeQuality);
static extern void MmsValue_setUtcTimeQuality(IntPtr self, byte timeQuality);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 MmsValue_toUnixTimestamp (IntPtr self);
static extern UInt32 MmsValue_toUnixTimestamp(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newBoolean ([MarshalAs(UnmanagedType.I1)] bool value);
static extern IntPtr MmsValue_newBoolean([MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newFloat (float value);
static extern IntPtr MmsValue_newFloat(float value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newDouble (double value);
static extern IntPtr MmsValue_newDouble(double value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newIntegerFromInt32 (Int32 integer);
static extern IntPtr MmsValue_newIntegerFromInt32(Int32 integer);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newUnsignedFromUint32(UInt32 integer);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newIntegerFromInt64 (Int64 integer);
static extern IntPtr MmsValue_newIntegerFromInt64(Int64 integer);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newBitString(int bitSize);
@ -188,18 +185,18 @@ namespace IEC61850
static extern bool MmsValue_equals(IntPtr self, IntPtr otherValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newBinaryTime ([MarshalAs(UnmanagedType.I1)] bool timeOfDay);
static extern IntPtr MmsValue_newBinaryTime([MarshalAs(UnmanagedType.I1)] bool timeOfDay);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setBinaryTime (IntPtr self, UInt64 timestamp);
static extern void MmsValue_setBinaryTime(IntPtr self, UInt64 timestamp);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern ulong MmsValue_getBinaryTimeAsUtcMs (IntPtr self);
static extern ulong MmsValue_getBinaryTimeAsUtcMs(IntPtr self);
[DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newUtcTimeByMsTime (UInt64 timestamp);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newUtcTimeByMsTime(UInt64 timestamp);
[DllImport("iec61850", CallingConvention=CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsValue_getDataAccessError(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
@ -221,82 +218,84 @@ namespace IEC61850
private bool responsableForDeletion = false; /* if .NET wrapper is responsable for the deletion of the native MmsValue instance */
internal MmsValue (IntPtr value)
internal MmsValue(IntPtr value)
{
valueReference = value;
this.responsableForDeletion = false;
responsableForDeletion = false;
}
public int EncodeMmsData(byte[] buffer, int bufPos, bool encode)
{
return MmsValue_encodeMmsData(this.valueReference, buffer, bufPos, encode);
return MmsValue_encodeMmsData(valueReference, buffer, bufPos, encode);
}
public int DecodeMmsData(int bufPos, int bufferLength, IntPtr endBufPo)
{
return MmsValue_decodeMmsData(this.valueReference, bufPos, bufferLength, endBufPo);
return MmsValue_decodeMmsData(valueReference, bufPos, bufferLength, endBufPo);
}
internal MmsValue (IntPtr value, bool responsableForDeletion)
internal MmsValue(IntPtr value, bool responsableForDeletion)
{
valueReference = value;
this.responsableForDeletion = responsableForDeletion;
}
public MmsValue (bool value)
public MmsValue(bool value)
{
valueReference = MmsValue_newBoolean (value);
valueReference = MmsValue_newBoolean(value);
}
public MmsValue (float value)
public MmsValue(float value)
{
valueReference = MmsValue_newFloat (value);
valueReference = MmsValue_newFloat(value);
}
public MmsValue (double value)
public MmsValue(double value)
{
valueReference = MmsValue_newDouble (value);
valueReference = MmsValue_newDouble(value);
}
public MmsValue (int value)
public MmsValue(int value)
{
valueReference = MmsValue_newIntegerFromInt32 (value);
valueReference = MmsValue_newIntegerFromInt32(value);
}
public MmsValue (UInt32 value)
public MmsValue(UInt32 value)
{
valueReference = MmsValue_newUnsignedFromUint32(value);
}
public MmsValue (long value)
public MmsValue(long value)
{
valueReference = MmsValue_newIntegerFromInt64 (value);
valueReference = MmsValue_newIntegerFromInt64(value);
}
/// <summary>
/// Create a new <see cref="IEC61850.Common.MmsValue"/> instance of type MMS_VISIBLE_STRING.
/// </summary>
/// <param name="value">Value.</param>
public MmsValue (string value)
public MmsValue(string value)
{
valueReference = MmsValue_newVisibleString(value);
}
public void Dispose()
{
lock (this) {
if (valueReference != IntPtr.Zero) {
lock (this)
{
if (valueReference != IntPtr.Zero)
{
if (responsableForDeletion)
MmsValue_delete (valueReference);
MmsValue_delete(valueReference);
valueReference = IntPtr.Zero;
}
}
}
~MmsValue ()
~MmsValue()
{
Dispose();
}
@ -329,7 +328,7 @@ namespace IEC61850
/// <param name='size'>
/// the current size of the octet string in bytes (defaults to 0)
/// </param>
public static MmsValue NewOctetString (int maxSize, int size = 0)
public static MmsValue NewOctetString(int maxSize, int size = 0)
{
IntPtr newValue = MmsValue_newOctetString(size, maxSize);
@ -339,11 +338,11 @@ namespace IEC61850
public MmsValue(byte[] octetString)
{
if (octetString.Length > 255)
throw new MmsValueException ("octet string too long");
throw new MmsValueException("octet string too long");
valueReference = MmsValue_newOctetString(octetString.Length, octetString.Length);
this.setOctetString (octetString);
setOctetString(octetString);
}
/// <summary>
@ -355,11 +354,11 @@ namespace IEC61850
public static MmsValue NewArray(MmsVariableSpecification elementType, int size)
{
if (size < 1)
throw new MmsValueException ("array requires at least one element");
throw new MmsValueException("array requires at least one element");
IntPtr newValue = MmsValue_createArray (elementType.self, size);
IntPtr newValue = MmsValue_createArray(elementType.self, size);
return new MmsValue (newValue, true);
return new MmsValue(newValue, true);
}
/// <summary>
@ -370,11 +369,11 @@ namespace IEC61850
public static MmsValue NewEmptyArray(int size)
{
if (size < 1)
throw new MmsValueException ("array requires at least one element");
throw new MmsValueException("array requires at least one element");
IntPtr newValue = MmsValue_createEmptyArray (size);
IntPtr newValue = MmsValue_createEmptyArray(size);
return new MmsValue (newValue, true);
return new MmsValue(newValue, true);
}
/// <summary>
@ -385,11 +384,11 @@ namespace IEC61850
public static MmsValue NewEmptyStructure(int size)
{
if (size < 1)
throw new MmsValueException ("structure requires at least one element");
throw new MmsValueException("structure requires at least one element");
IntPtr newValue = MmsValue_createEmptyStructure (size);
IntPtr newValue = MmsValue_createEmptyStructure(size);
return new MmsValue (newValue, true);
return new MmsValue(newValue, true);
}
@ -400,17 +399,18 @@ namespace IEC61850
/// <param name="largeFormat">If set to <c>true</c> large 6 byte format.</param>
public static MmsValue NewBinaryTime(bool largeFormat)
{
IntPtr newValue = MmsValue_newBinaryTime (largeFormat);
IntPtr newValue = MmsValue_newBinaryTime(largeFormat);
return new MmsValue (newValue, true);
return new MmsValue(newValue, true);
}
/// <summary>
/// Sets the binary time.
/// </summary>
/// <param name="timestamp">Timestamp.</param>
public void SetBinaryTime(UInt64 timestamp) {
MmsValue_setBinaryTime (this.valueReference, timestamp);
public void SetBinaryTime(UInt64 timestamp)
{
MmsValue_setBinaryTime(valueReference, timestamp);
}
/// <summary>
@ -424,12 +424,14 @@ namespace IEC61850
/// The UTC time in ms.
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public ulong GetBinaryTimeAsUtcMs ()
public ulong GetBinaryTimeAsUtcMs()
{
if (GetType() == MmsType.MMS_BINARY_TIME)
{
if (GetType () == MmsType.MMS_BINARY_TIME) {
return MmsValue_getBinaryTimeAsUtcMs (valueReference);
} else
throw new MmsValueException ("Value is not a time type");
return MmsValue_getBinaryTimeAsUtcMs(valueReference);
}
else
throw new MmsValueException("Value is not a time type");
}
/// <summary>
@ -437,11 +439,11 @@ namespace IEC61850
/// </summary>
/// <returns>the new MmsValue instance.</returns>
/// <param name="timestamp">the time value as milliseconds since epoch (1.1.1970 UTC).</param>
public static MmsValue NewUtcTime (UInt64 timestamp)
public static MmsValue NewUtcTime(UInt64 timestamp)
{
IntPtr newValue = MmsValue_newUtcTimeByMsTime (timestamp);
IntPtr newValue = MmsValue_newUtcTimeByMsTime(timestamp);
return new MmsValue (newValue, true);
return new MmsValue(newValue, true);
}
/// <summary>
@ -471,9 +473,9 @@ namespace IEC61850
/// <returns>
/// The type.
/// </returns>
public new MmsType GetType ()
public new MmsType GetType()
{
return (MmsType)MmsValue_getType (valueReference);
return (MmsType)MmsValue_getType(valueReference);
}
/// <summary>
@ -487,18 +489,22 @@ namespace IEC61850
/// the number of elements (array/structure elements, octets, bits depending on type)
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public int Size ()
public int Size()
{
if ((GetType() == MmsType.MMS_ARRAY) || (GetType() == MmsType.MMS_STRUCTURE))
{
return MmsValue_getArraySize(valueReference);
}
else if (GetType() == MmsType.MMS_BIT_STRING)
{
if ((GetType () == MmsType.MMS_ARRAY) || (GetType () == MmsType.MMS_STRUCTURE)) {
return MmsValue_getArraySize (valueReference);
} else if (GetType () == MmsType.MMS_BIT_STRING) {
return MmsValue_getBitStringSize(valueReference);
}
else if (GetType () == MmsType.MMS_OCTET_STRING) {
else if (GetType() == MmsType.MMS_OCTET_STRING)
{
return MmsValue_getOctetStringSize(valueReference);
}
else
throw new MmsValueException ("Operation not supported for this type");
throw new MmsValueException("Operation not supported for this type");
}
/// <summary>
@ -507,13 +513,14 @@ namespace IEC61850
/// <returns>
/// The maximum size (in bytes) of the octet string
/// </returns>
public int MaxSize ()
public int MaxSize()
{
if (GetType() == MmsType.MMS_OCTET_STRING)
{
if (GetType () == MmsType.MMS_OCTET_STRING) {
return MmsValue_getOctetStringMaxSize(valueReference);
}
else
throw new MmsValueException ("Operation not supported for this type");
throw new MmsValueException("Operation not supported for this type");
}
/// <summary>
@ -525,11 +532,12 @@ namespace IEC61850
/// Byte array containing the bytes of the octet string.
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public byte[] getOctetString ()
public byte[] getOctetString()
{
if (GetType() == MmsType.MMS_OCTET_STRING)
{
if (GetType () == MmsType.MMS_OCTET_STRING) {
IntPtr buffer = MmsValue_getOctetStringBuffer(valueReference);
int bufferSize = this.Size();
int bufferSize = Size();
byte[] octetString = new byte[bufferSize];
@ -538,7 +546,7 @@ namespace IEC61850
return octetString;
}
else
throw new MmsValueException ("Operation not supported for this type");
throw new MmsValueException("Operation not supported for this type");
}
/// <summary>
@ -546,17 +554,18 @@ namespace IEC61850
/// </summary>
/// <param name="octetString">Byte array containing the bytes of the octet string.</param>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type or the byte array is too large.</exception>
public void setOctetString (byte[] octetString)
public void setOctetString(byte[] octetString)
{
if (GetType() == MmsType.MMS_OCTET_STRING)
{
if (GetType () == MmsType.MMS_OCTET_STRING) {
if (this.MaxSize() < octetString.Length)
if (MaxSize() < octetString.Length)
throw new MmsValueException("octet string is to large");
MmsValue_setOctetString(valueReference, octetString, octetString.Length);
}
else
throw new MmsValueException ("Operation not supported for this type");
throw new MmsValueException("Operation not supported for this type");
}
/// <summary>
@ -590,22 +599,26 @@ namespace IEC61850
/// </param>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
/// <exception cref="MmsValueException">This exception is thrown if the index is out of range.</exception>
public MmsValue GetElement (int index)
public MmsValue GetElement(int index)
{
MmsType type = GetType ();
MmsType type = GetType();
if ((type == MmsType.MMS_ARRAY) || (type == MmsType.MMS_STRUCTURE)) {
if ((index >= 0) && (index < Size ())) {
IntPtr value = MmsValue_getElement (valueReference, index);
if ((type == MmsType.MMS_ARRAY) || (type == MmsType.MMS_STRUCTURE))
{
if ((index >= 0) && (index < Size()))
{
IntPtr value = MmsValue_getElement(valueReference, index);
if (value == IntPtr.Zero)
return null;
else
return new MmsValue (value);
} else
throw new MmsValueException ("Index out of bounds");
} else
throw new MmsValueException ("Value is of wrong type");
return new MmsValue(value);
}
else
throw new MmsValueException("Index out of bounds");
}
else
throw new MmsValueException("Value is of wrong type");
}
/// <summary>
@ -674,12 +687,12 @@ namespace IEC61850
/// The UTC time in seconds (UNIX time stamp).
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public UInt32 ToUnixTimestamp ()
public UInt32 ToUnixTimestamp()
{
if (GetType () == MmsType.MMS_UTC_TIME)
return MmsValue_toUnixTimestamp (valueReference);
if (GetType() == MmsType.MMS_UTC_TIME)
return MmsValue_toUnixTimestamp(valueReference);
else
throw new MmsValueException ("Value is not a time type");
throw new MmsValueException("Value is not a time type");
}
/// <summary>
@ -692,10 +705,12 @@ namespace IEC61850
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public void SetUtcTimeMs(ulong timeval)
{
if (GetType () == MmsType.MMS_UTC_TIME) {
if (GetType() == MmsType.MMS_UTC_TIME)
{
MmsValue_setUtcTimeMs(valueReference, timeval);
} else
throw new MmsValueException ("Value is not a time type");
}
else
throw new MmsValueException("Value is not a time type");
}
/// <summary>
@ -709,12 +724,14 @@ namespace IEC61850
/// The UTC time in ms.
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public ulong GetUtcTimeInMs ()
public ulong GetUtcTimeInMs()
{
if (GetType() == MmsType.MMS_UTC_TIME)
{
if (GetType () == MmsType.MMS_UTC_TIME) {
return MmsValue_getUtcTimeInMs (valueReference);
} else
throw new MmsValueException ("Value is not a time type");
return MmsValue_getUtcTimeInMs(valueReference);
}
else
throw new MmsValueException("Value is not a time type");
}
/// <summary>
@ -776,8 +793,8 @@ namespace IEC61850
/// <param name="timeQuality">Time quality.</param>
public void SetUtcTimeQuality(byte timeQuality)
{
if (GetType () == MmsType.MMS_UTC_TIME)
MmsValue_setUtcTimeQuality (valueReference, timeQuality);
if (GetType() == MmsType.MMS_UTC_TIME)
MmsValue_setUtcTimeQuality(valueReference, timeQuality);
else
throw new MmsValueException("Value is not a time type");
}
@ -791,11 +808,11 @@ namespace IEC61850
/// <param name='msTime'>
/// the millisecond time
/// </param>
public static DateTimeOffset MsTimeToDateTimeOffset (UInt64 msTime)
public static DateTimeOffset MsTimeToDateTimeOffset(UInt64 msTime)
{
DateTimeOffset retVal = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
DateTimeOffset retVal = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
return retVal.AddMilliseconds ((double) msTime);
return retVal.AddMilliseconds(msTime);
}
/// <summary>
@ -809,12 +826,12 @@ namespace IEC61850
/// the value as DataTimeOffset instance
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public DateTimeOffset GetUtcTimeAsDateTimeOffset ()
public DateTimeOffset GetUtcTimeAsDateTimeOffset()
{
if (GetType () == MmsType.MMS_UTC_TIME)
return MsTimeToDateTimeOffset (GetUtcTimeInMs ());
if (GetType() == MmsType.MMS_UTC_TIME)
return MsTimeToDateTimeOffset(GetUtcTimeInMs());
else
throw new MmsValueException ("Value is not a time type");
throw new MmsValueException("Value is not a time type");
}
@ -829,12 +846,12 @@ namespace IEC61850
/// the value if the object as 32 bit signed integer
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public Int32 ToInt32 ()
public Int32 ToInt32()
{
if (GetType () != MmsType.MMS_INTEGER)
throw new MmsValueException ("Value type is not integer");
if (GetType() != MmsType.MMS_INTEGER)
throw new MmsValueException("Value type is not integer");
return MmsValue_toInt32 (valueReference);
return MmsValue_toInt32(valueReference);
}
/// <summary>
@ -863,12 +880,12 @@ namespace IEC61850
/// the value if the object as 64 bit signed integer
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public Int64 ToInt64 ()
public Int64 ToInt64()
{
if (GetType () != MmsType.MMS_INTEGER)
throw new MmsValueException ("Value type is not integer");
if (GetType() != MmsType.MMS_INTEGER)
throw new MmsValueException("Value type is not integer");
return MmsValue_toInt64 (valueReference);
return MmsValue_toInt64(valueReference);
}
/// <summary>
@ -882,25 +899,25 @@ namespace IEC61850
/// the value if the object as 32 bit unsigned integer
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public UInt32 ToUint32 ()
public UInt32 ToUint32()
{
if (GetType () != MmsType.MMS_UNSIGNED)
throw new MmsValueException ("Value type is not unsigned");
if (GetType() != MmsType.MMS_UNSIGNED)
throw new MmsValueException("Value type is not unsigned");
return MmsValue_toUint32 (valueReference);
return MmsValue_toUint32(valueReference);
}
public UInt32 BitStringToUInt32 ()
public UInt32 BitStringToUInt32()
{
if (GetType () != MmsType.MMS_BIT_STRING)
if (GetType() != MmsType.MMS_BIT_STRING)
throw new MmsValueException("Value type is not bit string");
return MmsValue_getBitStringAsInteger(valueReference);
}
public void BitStringFromUInt32 (UInt32 intValue)
public void BitStringFromUInt32(UInt32 intValue)
{
if (GetType () != MmsType.MMS_BIT_STRING)
if (GetType() != MmsType.MMS_BIT_STRING)
throw new MmsValueException("Value type is not bit string");
MmsValue_setBitStringFromInteger(valueReference, intValue);
@ -922,17 +939,17 @@ namespace IEC61850
MmsValue_setBitStringFromIntegerBigEndian(valueReference, intValue);
}
public void SetBit (int bitPos, bool bitValue)
public void SetBit(int bitPos, bool bitValue)
{
if (GetType () != MmsType.MMS_BIT_STRING)
if (GetType() != MmsType.MMS_BIT_STRING)
throw new MmsValueException("Value type is not bit string");
MmsValue_setBitStringBit(valueReference, bitPos, bitValue);
}
public bool GetBit (int bitPos)
public bool GetBit(int bitPos)
{
if (GetType () != MmsType.MMS_BIT_STRING)
if (GetType() != MmsType.MMS_BIT_STRING)
throw new MmsValueException("Value type is not bit string");
return MmsValue_getBitStringBit(valueReference, bitPos);
@ -965,12 +982,12 @@ namespace IEC61850
/// The boolean value
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public bool GetBoolean ()
public bool GetBoolean()
{
if (GetType () == MmsType.MMS_BOOLEAN)
return MmsValue_getBoolean (valueReference);
if (GetType() == MmsType.MMS_BOOLEAN)
return MmsValue_getBoolean(valueReference);
else
throw new MmsValueException ("Value type is not boolean");
throw new MmsValueException("Value type is not boolean");
}
/// <summary>
@ -995,12 +1012,12 @@ namespace IEC61850
/// The float value
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public float ToFloat ()
public float ToFloat()
{
if (GetType () == MmsType.MMS_FLOAT)
return MmsValue_toFloat (valueReference);
if (GetType() == MmsType.MMS_FLOAT)
return MmsValue_toFloat(valueReference);
else
throw new MmsValueException ("Value type is not float");
throw new MmsValueException("Value type is not float");
}
/// <summary>
@ -1010,12 +1027,12 @@ namespace IEC61850
/// the new value to set
/// </param>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public void SetFloat (float value)
public void SetFloat(float value)
{
if (GetType () == MmsType.MMS_FLOAT)
MmsValue_setFloat (valueReference, value);
if (GetType() == MmsType.MMS_FLOAT)
MmsValue_setFloat(valueReference, value);
else
throw new MmsValueException ("Value type is not float");
throw new MmsValueException("Value type is not float");
}
/// <summary>
@ -1025,12 +1042,12 @@ namespace IEC61850
/// The float value
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public double ToDouble ()
public double ToDouble()
{
if (GetType () == MmsType.MMS_FLOAT)
return MmsValue_toDouble (valueReference);
if (GetType() == MmsType.MMS_FLOAT)
return MmsValue_toDouble(valueReference);
else
throw new MmsValueException ("Value type is not float");
throw new MmsValueException("Value type is not float");
}
/// <summary>
@ -1040,12 +1057,12 @@ namespace IEC61850
/// the new value to set
/// </param>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
public void SetDouble (double value)
public void SetDouble(double value)
{
if (GetType () == MmsType.MMS_FLOAT)
MmsValue_setDouble (valueReference, value);
if (GetType() == MmsType.MMS_FLOAT)
MmsValue_setDouble(valueReference, value);
else
throw new MmsValueException ("Value type is not float");
throw new MmsValueException("Value type is not float");
}
/// <summary>
@ -1083,34 +1100,35 @@ namespace IEC61850
return new MmsValue(clonePtr, true);
}
public override bool Equals (object obj)
public override bool Equals(object obj)
{
MmsValue otherValue = (MmsValue) obj;
MmsValue otherValue = (MmsValue)obj;
return MmsValue_equals(this.valueReference, otherValue.valueReference);
return MmsValue_equals(valueReference, otherValue.valueReference);
}
// override standard ToString() method
public override string ToString ()
public override string ToString()
{
switch (GetType())
{
switch (GetType ()) {
case MmsType.MMS_VISIBLE_STRING:
case MmsType.MMS_STRING:
return Marshal.PtrToStringAnsi (MmsValue_toString (valueReference));
return Marshal.PtrToStringAnsi(MmsValue_toString(valueReference));
case MmsType.MMS_BOOLEAN:
return GetBoolean ().ToString ();
return GetBoolean().ToString();
case MmsType.MMS_INTEGER:
return ToInt64 ().ToString ();
return ToInt64().ToString();
case MmsType.MMS_UNSIGNED:
return ToUint32 ().ToString ();
return ToUint32().ToString();
case MmsType.MMS_FLOAT:
return ToDouble ().ToString ();
return ToDouble().ToString();
case MmsType.MMS_UTC_TIME:
return GetUtcTimeAsDateTimeOffset ().ToString ();
return GetUtcTimeAsDateTimeOffset().ToString();
case MmsType.MMS_BINARY_TIME:
return (MsTimeToDateTimeOffset (GetBinaryTimeAsUtcMs ()).ToString ());
return (MsTimeToDateTimeOffset(GetBinaryTimeAsUtcMs()).ToString());
case MmsType.MMS_OCTET_STRING:
return BitConverter.ToString (getOctetString ());
return BitConverter.ToString(getOctetString());
case MmsType.MMS_BIT_STRING:
return GetBitStringAsString();
case MmsType.MMS_STRUCTURE:
@ -1119,13 +1137,17 @@ namespace IEC61850
bool first = true;
foreach (MmsValue element in this) {
if (first) {
retString += element.ToString ();
foreach (MmsValue element in this)
{
if (first)
{
retString += element.ToString();
first = false;
} else {
retString += ", " + element.ToString ();
}
else
{
retString += ", " + element.ToString();
}
}
@ -1139,13 +1161,17 @@ namespace IEC61850
bool first = true;
foreach (MmsValue element in this) {
if (first) {
retString += element.ToString ();
foreach (MmsValue element in this)
{
if (first)
{
retString += element.ToString();
first = false;
} else {
retString += ", " + element.ToString ();
}
else
{
retString += ", " + element.ToString();
}
}
@ -1161,9 +1187,9 @@ namespace IEC61850
}
}
IEnumerator IEnumerable.GetEnumerator ()
IEnumerator IEnumerable.GetEnumerator()
{
return new MmsValueEnumerator (this);
return new MmsValueEnumerator(this);
}
private class MmsValueEnumerator : IEnumerator
@ -1171,27 +1197,28 @@ namespace IEC61850
private MmsValue value;
private int index = -1;
public MmsValueEnumerator (MmsValue value)
public MmsValueEnumerator(MmsValue value)
{
this.value = value;
}
#region IEnumerator Members
public void Reset ()
public void Reset()
{
index = -1;
}
public object Current {
public object Current
{
get { return value.GetElement (index);}
get { return value.GetElement(index); }
}
public bool MoveNext ()
public bool MoveNext()
{
index++;
if (index >= value.Size ())
if (index >= value.Size())
return false;
else
return true;
@ -1204,7 +1231,7 @@ namespace IEC61850
public class MmsValueException : Exception
{
public MmsValueException (string message)
public MmsValueException(string message)
: base(message)
{
}

@ -1,7 +1,7 @@
/*
* MmsVariableSpecification.cs
*
* Copyright 2014-2024 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,11 +21,9 @@
* See COPYING file for the complete license text.
*/
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace IEC61850
@ -73,7 +71,7 @@ namespace IEC61850
internal MmsVariableSpecification(IntPtr self, MmsVariableSpecification parent)
{
this.self = self;
this.responsableForDeletion = false;
responsableForDeletion = false;
this.parent = parent;
}

@ -1,7 +1,7 @@
/*
* ReportControlBlock.cs
*
* Copyright 2014-2018 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,11 +20,9 @@
*
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using IEC61850.Common;
namespace IEC61850
{
@ -36,10 +34,10 @@ namespace IEC61850
/// </summary>
/// <param name="report">represents the received report. DON'T use this object
/// outside the scope of the report handler!</param>
public delegate void ReportHandler (Report report, object parameter);
public delegate void ReportHandler(Report report, object parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void InternalReportHandler (IntPtr parameter, IntPtr report);
internal delegate void InternalReportHandler(IntPtr parameter, IntPtr report);
/// <summary>
/// Report control block (RCB) representation.
@ -52,106 +50,106 @@ namespace IEC61850
public class ReportControlBlock : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_create (string dataAttributeReference);
static extern IntPtr ClientReportControlBlock_create(string dataAttributeReference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_destroy (IntPtr self);
static extern void ClientReportControlBlock_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_isBuffered (IntPtr self);
static extern bool ClientReportControlBlock_isBuffered(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_getRptId (IntPtr self);
static extern IntPtr ClientReportControlBlock_getRptId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setRptId (IntPtr self, string rptId);
static extern void ClientReportControlBlock_setRptId(IntPtr self, string rptId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getRptEna (IntPtr self);
static extern bool ClientReportControlBlock_getRptEna(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setRptEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getResv (IntPtr self);
static extern bool ClientReportControlBlock_getResv(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setResv (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool resv);
static extern void ClientReportControlBlock_setResv(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool resv);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_getDataSetReference (IntPtr self);
static extern IntPtr ClientReportControlBlock_getDataSetReference(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setDataSetReference (IntPtr self, string dataSetReference);
static extern void ClientReportControlBlock_setDataSetReference(IntPtr self, string dataSetReference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientReportControlBlock_getConfRev (IntPtr self);
static extern UInt32 ClientReportControlBlock_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientReportControlBlock_getOptFlds (IntPtr self);
static extern int ClientReportControlBlock_getOptFlds(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setOptFlds (IntPtr self, int optFlds);
static extern void ClientReportControlBlock_setOptFlds(IntPtr self, int optFlds);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientReportControlBlock_getBufTm (IntPtr self);
static extern UInt32 ClientReportControlBlock_getBufTm(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setBufTm (IntPtr self, UInt32 bufTm);
static extern void ClientReportControlBlock_setBufTm(IntPtr self, UInt32 bufTm);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientReportControlBlock_getSqNum (IntPtr self);
static extern UInt16 ClientReportControlBlock_getSqNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientReportControlBlock_getTrgOps (IntPtr self);
static extern int ClientReportControlBlock_getTrgOps(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setTrgOps (IntPtr self, int trgOps);
static extern void ClientReportControlBlock_setTrgOps(IntPtr self, int trgOps);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientReportControlBlock_getIntgPd (IntPtr self);
static extern UInt32 ClientReportControlBlock_getIntgPd(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setIntgPd (IntPtr self, UInt32 intgPd);
static extern void ClientReportControlBlock_setIntgPd(IntPtr self, UInt32 intgPd);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getGI (IntPtr self);
static extern bool ClientReportControlBlock_getGI(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setGI (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool gi);
static extern void ClientReportControlBlock_setGI(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool gi);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getPurgeBuf (IntPtr self);
static extern bool ClientReportControlBlock_getPurgeBuf(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setPurgeBuf (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool purgeBuf);
static extern void ClientReportControlBlock_setPurgeBuf(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool purgeBuf);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_hasResvTms(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern Int16 ClientReportControlBlock_getResvTms (IntPtr self);
static extern Int16 ClientReportControlBlock_getResvTms(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setResvTms (IntPtr self, Int16 resvTms);
static extern void ClientReportControlBlock_setResvTms(IntPtr self, Int16 resvTms);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_getEntryId (IntPtr self);
static extern IntPtr ClientReportControlBlock_getEntryId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setEntryId (IntPtr self, IntPtr entryId);
static extern void ClientReportControlBlock_setEntryId(IntPtr self, IntPtr entryId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt64 ClientReportControlBlock_getEntryTime (IntPtr self);
static extern UInt64 ClientReportControlBlock_getEntryTime(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_getOwner (IntPtr self);
static extern IntPtr ClientReportControlBlock_getOwner(IntPtr self);
internal IntPtr self;
@ -177,7 +175,7 @@ namespace IEC61850
private bool reportHandlerInstalled = false;
private event InternalReportHandler internalHandler = null;
private void resetSendFlags ()
private void resetSendFlags()
{
flagRptId = false;
flagRptEna = false;
@ -197,28 +195,31 @@ namespace IEC61850
private Report report = null;
private void internalReportHandler (IntPtr parameter, IntPtr report)
private void internalReportHandler(IntPtr parameter, IntPtr report)
{
try
{
try {
if (this.report == null)
this.report = new Report (report);
this.report = new Report(report);
if (reportHandler != null)
reportHandler(this.report, reportHandlerParameter);
} catch (Exception e)
}
catch (Exception e)
{
// older versions of mono 2.10 (for linux?) cause this exception
Console.WriteLine(e.Message);
}
}
internal ReportControlBlock (string objectReference, IedConnection iedConnection, IntPtr connection)
internal ReportControlBlock(string objectReference, IedConnection iedConnection, IntPtr connection)
{
self = ClientReportControlBlock_create (objectReference);
self = ClientReportControlBlock_create(objectReference);
if (self != IntPtr.Zero) {
if (self != IntPtr.Zero)
{
this.iedConnection = iedConnection;
this.objectReference = objectReference;
}
@ -234,14 +235,16 @@ namespace IEC61850
/// <see cref="IEC61850.Client.ReportControlBlock"/> was occupying.</remarks>
public void Dispose()
{
lock (this) {
if (self != IntPtr.Zero) {
lock (this)
{
if (self != IntPtr.Zero)
{
iedConnection.UninstallReportHandler (objectReference);
iedConnection.UninstallReportHandler(objectReference);
iedConnection.RemoveRCB (this);
iedConnection.RemoveRCB(this);
ClientReportControlBlock_destroy (self);
ClientReportControlBlock_destroy(self);
self = IntPtr.Zero;
}
@ -250,12 +253,12 @@ namespace IEC61850
~ReportControlBlock()
{
Dispose ();
Dispose();
}
public string GetObjectReference ()
public string GetObjectReference()
{
return this.objectReference;
return objectReference;
}
/// <summary>
@ -272,22 +275,23 @@ namespace IEC61850
/// <param name='parameter'>
/// parameter is passed to the handler when the handler is invoked.
/// </param>
public void InstallReportHandler (ReportHandler reportHandler, object parameter)
public void InstallReportHandler(ReportHandler reportHandler, object parameter)
{
this.reportHandler = new ReportHandler(reportHandler);
this.reportHandlerParameter = parameter;
reportHandlerParameter = parameter;
if (reportHandlerInstalled == false) {
if (reportHandlerInstalled == false)
{
string reportId = this.GetRptId ();
string reportId = GetRptId();
if (internalHandler == null)
{
internalHandler = new InternalReportHandler(internalReportHandler);
}
iedConnection.InstallReportHandler (objectReference, reportId, internalHandler);
iedConnection.InstallReportHandler(objectReference, reportId, internalHandler);
reportHandlerInstalled = true;
}
@ -297,14 +301,14 @@ namespace IEC61850
/// Read all RCB values from the server
/// </summary>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public void GetRCBValues ()
public void GetRCBValues()
{
int error;
iedConnection.GetRCBValues (out error, objectReference, self);
iedConnection.GetRCBValues(out error, objectReference, self);
if (error != 0)
throw new IedConnectionException ("getRCBValues service failed", error);
throw new IedConnectionException("getRCBValues service failed", error);
}
/// <summary>
@ -327,9 +331,9 @@ namespace IEC61850
/// The RCB values are sent by a single MMS write request.
/// </description>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public void SetRCBValues ()
public void SetRCBValues()
{
SetRCBValues (true);
SetRCBValues(true);
}
private UInt32 CreateParametersMask()
@ -403,7 +407,7 @@ namespace IEC61850
/// <param name='singleRequest'>
/// If true the values are sent by single MMS write request. Otherwise the values are all sent by their own MMS write requests.
/// </param>
public void SetRCBValues (bool singleRequest)
public void SetRCBValues(bool singleRequest)
{
UInt32 parametersMask = CreateParametersMask();
@ -411,18 +415,20 @@ namespace IEC61850
int error;
iedConnection.SetRCBValues (out error, self, parametersMask, singleRequest);
iedConnection.SetRCBValues(out error, self, parametersMask, singleRequest);
resetSendFlags();
if (error != 0)
throw new IedConnectionException ("setRCBValues service failed", error);
throw new IedConnectionException("setRCBValues service failed", error);
if (flagRptId) {
if (flagRptId)
{
if (reportHandlerInstalled) {
if (reportHandlerInstalled)
{
reportHandlerInstalled = false;
InstallReportHandler(this.reportHandler, this.reportHandlerParameter);
InstallReportHandler(reportHandler, reportHandlerParameter);
}
}
}
@ -433,9 +439,9 @@ namespace IEC61850
/// <returns>
/// <c>true</c> if this instance is a buffered RCB; otherwise, <c>false</c>.
/// </returns>
public bool IsBuffered ()
public bool IsBuffered()
{
return ClientReportControlBlock_isBuffered (self);
return ClientReportControlBlock_isBuffered(self);
}
/// <summary>
@ -447,9 +453,9 @@ namespace IEC61850
/// <returns>
/// The entry time as ms timestamp
/// </returns>
public UInt64 GetEntryTime ()
public UInt64 GetEntryTime()
{
return ClientReportControlBlock_getEntryTime (self);
return ClientReportControlBlock_getEntryTime(self);
}
/// <summary>
@ -461,13 +467,13 @@ namespace IEC61850
/// <returns>
/// The entry time as DataTimeOffset
/// </returns>
public DateTimeOffset GetEntryTimeAsDateTimeOffset ()
public DateTimeOffset GetEntryTimeAsDateTimeOffset()
{
UInt64 entryTime = GetEntryTime ();
UInt64 entryTime = GetEntryTime();
DateTimeOffset retVal = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
DateTimeOffset retVal = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
return retVal.AddMilliseconds (entryTime);
return retVal.AddMilliseconds(entryTime);
}
/// <summary>
@ -479,14 +485,15 @@ namespace IEC61850
/// <returns>The entry ID</returns>
public byte[] GetEntryID()
{
IntPtr entryIdRef = ClientReportControlBlock_getEntryId (self);
IntPtr entryIdRef = ClientReportControlBlock_getEntryId(self);
if (entryIdRef == IntPtr.Zero)
return null;
else {
MmsValue entryId = new MmsValue (entryIdRef);
else
{
MmsValue entryId = new MmsValue(entryIdRef);
return entryId.getOctetString ();
return entryId.getOctetString();
}
}
@ -496,11 +503,11 @@ namespace IEC61850
MmsValue entryID = MmsValue.NewOctetString (entryId.Length);
MmsValue entryID = MmsValue.NewOctetString(entryId.Length);
entryID.setOctetString (entryId);
entryID.setOctetString(entryId);
ClientReportControlBlock_setEntryId (self, entryID.valueReference);
ClientReportControlBlock_setEntryId(self, entryID.valueReference);
}
@ -512,11 +519,11 @@ namespace IEC61850
/// <returns>
/// The data set reference.
/// </returns>
public string GetDataSetReference ()
public string GetDataSetReference()
{
IntPtr dataSetRefPtr = ClientReportControlBlock_getDataSetReference (self);
IntPtr dataSetRefPtr = ClientReportControlBlock_getDataSetReference(self);
return Marshal.PtrToStringAnsi (dataSetRefPtr);
return Marshal.PtrToStringAnsi(dataSetRefPtr);
}
/// <summary>
@ -525,9 +532,9 @@ namespace IEC61850
/// <returns>
/// The data set reference.
/// </returns>
public void SetDataSetReference (string dataSetReference)
public void SetDataSetReference(string dataSetReference)
{
ClientReportControlBlock_setDataSetReference (self, dataSetReference);
ClientReportControlBlock_setDataSetReference(self, dataSetReference);
flagDataSetReference = true;
}
@ -538,11 +545,11 @@ namespace IEC61850
/// <returns>
/// The report identifier.
/// </returns>
public string GetRptId ()
public string GetRptId()
{
IntPtr rptIdPtr = ClientReportControlBlock_getRptId (self);
IntPtr rptIdPtr = ClientReportControlBlock_getRptId(self);
return Marshal.PtrToStringAnsi (rptIdPtr);
return Marshal.PtrToStringAnsi(rptIdPtr);
}
/// <summary>
@ -551,7 +558,7 @@ namespace IEC61850
/// <param name='rptId'>
/// The new RptId
/// </param>
public void SetRptId (string rptId)
public void SetRptId(string rptId)
{
ClientReportControlBlock_setRptId(self, rptId);
flagRptId = true;
@ -563,9 +570,9 @@ namespace IEC61850
/// <returns>
/// true, if reporting is enabled, false otherwise
/// </returns>
public bool GetRptEna ()
public bool GetRptEna()
{
return ClientReportControlBlock_getRptEna (self);
return ClientReportControlBlock_getRptEna(self);
}
/// <summary>
@ -574,9 +581,9 @@ namespace IEC61850
/// <param name='rptEna'>
/// true to enable reporting, false to disable
/// </param>
public void SetRptEna (bool rptEna)
public void SetRptEna(bool rptEna)
{
ClientReportControlBlock_setRptEna (self, rptEna);
ClientReportControlBlock_setRptEna(self, rptEna);
flagRptEna = true;
}
@ -584,7 +591,7 @@ namespace IEC61850
/// Get the purgeBuf flag of the report control block
/// </summary>
/// <returns>the prugeBuf value</returns>
public bool GetPurgeBuf ()
public bool GetPurgeBuf()
{
return ClientReportControlBlock_getPurgeBuf(self);
}
@ -594,7 +601,7 @@ namespace IEC61850
/// </summary>
/// <description>This is only for buffered RCBs. If set to true the report buffer of a buffered RCB will be cleaned.</description>
/// <param name="purgeBuf">set to true to flush report buffer</param>
public void SetPurgeBuf (bool purgeBuf)
public void SetPurgeBuf(bool purgeBuf)
{
ClientReportControlBlock_setPurgeBuf(self, purgeBuf);
flagPurgeBuf = true;
@ -608,7 +615,7 @@ namespace IEC61850
/// </returns>
public UInt32 GetBufTm()
{
return ClientReportControlBlock_getBufTm (self);
return ClientReportControlBlock_getBufTm(self);
}
/// <summary>
@ -617,9 +624,9 @@ namespace IEC61850
/// <param name='bufTm'>
/// Buffer time is ms.
/// </param>
public void SetBufTm (UInt32 bufTm)
public void SetBufTm(UInt32 bufTm)
{
ClientReportControlBlock_setBufTm (self, bufTm);
ClientReportControlBlock_setBufTm(self, bufTm);
flagBufTm = true;
}
@ -630,9 +637,9 @@ namespace IEC61850
/// <returns>
/// true, if GI flag is set
/// </returns>
public bool GetGI ()
public bool GetGI()
{
return ClientReportControlBlock_getGI (self);
return ClientReportControlBlock_getGI(self);
}
/// <summary>
@ -641,9 +648,9 @@ namespace IEC61850
/// <param name='GI'>
/// request general interrogation of true
/// </param>
public void SetGI (bool GI)
public void SetGI(bool GI)
{
ClientReportControlBlock_setGI (self, GI);
ClientReportControlBlock_setGI(self, GI);
flagGI = true;
}
@ -653,9 +660,9 @@ namespace IEC61850
/// <returns>
/// true, the RCB is reserver by a client
/// </returns>
public bool GetResv ()
public bool GetResv()
{
return ClientReportControlBlock_getResv (self);
return ClientReportControlBlock_getResv(self);
}
/// <summary>
@ -664,9 +671,9 @@ namespace IEC61850
/// <returns>
/// The conf rev.
/// </returns>
public UInt32 GetConfRev ()
public UInt32 GetConfRev()
{
return ClientReportControlBlock_getConfRev (self);
return ClientReportControlBlock_getConfRev(self);
}
/// <summary>
@ -675,9 +682,9 @@ namespace IEC61850
/// <param name='resv'>
/// true: reserver this RCB for exclusive use
/// </param>
public void SetResv (bool resv)
public void SetResv(bool resv)
{
ClientReportControlBlock_setResv (self, resv);
ClientReportControlBlock_setResv(self, resv);
flagResv = true;
}
@ -689,7 +696,7 @@ namespace IEC61850
/// </returns>
public TriggerOptions GetTrgOps()
{
return (TriggerOptions) ClientReportControlBlock_getTrgOps (self);
return (TriggerOptions)ClientReportControlBlock_getTrgOps(self);
}
/// <summary>
@ -700,7 +707,7 @@ namespace IEC61850
/// </param>
public void SetTrgOps(TriggerOptions trgOps)
{
ClientReportControlBlock_setTrgOps (self, (int) trgOps);
ClientReportControlBlock_setTrgOps(self, (int)trgOps);
flagTrgOps = true;
}
@ -711,9 +718,9 @@ namespace IEC61850
/// <returns>
/// integrity period in ms
/// </returns>
public UInt32 GetIntgPd ()
public UInt32 GetIntgPd()
{
return ClientReportControlBlock_getIntgPd (self);
return ClientReportControlBlock_getIntgPd(self);
}
/// <summary>
@ -722,9 +729,9 @@ namespace IEC61850
/// <param name='intgPd'>
/// integrity period in ms
/// </param>
public void SetIntgPd (UInt32 intgPd)
public void SetIntgPd(UInt32 intgPd)
{
ClientReportControlBlock_setIntgPd (self, intgPd);
ClientReportControlBlock_setIntgPd(self, intgPd);
flagIntgPd = true;
}
@ -736,7 +743,7 @@ namespace IEC61850
/// </returns>
public ReportOptions GetOptFlds()
{
return (ReportOptions) ClientReportControlBlock_getOptFlds (self);
return (ReportOptions)ClientReportControlBlock_getOptFlds(self);
}
/// <summary>
@ -747,7 +754,7 @@ namespace IEC61850
/// </param>
public void SetOptFlds(ReportOptions optFlds)
{
ClientReportControlBlock_setOptFlds (self, (int)optFlds);
ClientReportControlBlock_setOptFlds(self, (int)optFlds);
flagOptFlds = true;
}

@ -1,7 +1,7 @@
/*
* Reporting.cs
*
* Copyright 2014-2018 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,11 +20,10 @@
*
* See COPYING file for the complete license text.
*/
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace IEC61850
{

@ -1,7 +1,7 @@
/*
* SampledValuesControlBlock.cs
*
* Copyright 2017 Michael Zillgith
* Copyright 2017-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,11 +20,9 @@
*
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using IEC61850.Common;
namespace IEC61850
{
@ -39,162 +37,163 @@ namespace IEC61850
public class SampledValuesControlBlock : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientSVControlBlock_create (IntPtr iedConnection, string reference);
static extern IntPtr ClientSVControlBlock_create(IntPtr iedConnection, string reference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientSVControlBlock_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientSVControlBlock_getLastComError (IntPtr self);
static extern int ClientSVControlBlock_getLastComError(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_isMulticast (IntPtr self);
static extern bool ClientSVControlBlock_isMulticast(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_setSvEna (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
static extern bool ClientSVControlBlock_setSvEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_setResv (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
static extern bool ClientSVControlBlock_setResv(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_getSvEna (IntPtr self);
static extern bool ClientSVControlBlock_getSvEna(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_getResv (IntPtr self);
static extern bool ClientSVControlBlock_getResv(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientSVControlBlock_getMsvID (IntPtr self);
static extern IntPtr ClientSVControlBlock_getMsvID(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientSVControlBlock_getDatSet (IntPtr self);
static extern IntPtr ClientSVControlBlock_getDatSet(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientSVControlBlock_getConfRev (IntPtr self);
static extern UInt32 ClientSVControlBlock_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientSVControlBlock_getSmpRate (IntPtr self);
static extern UInt16 ClientSVControlBlock_getSmpRate(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientSVControlBlock_getOptFlds (IntPtr self);
static extern int ClientSVControlBlock_getOptFlds(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern byte ClientSVControlBlock_getSmpMod(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientSVControlBlock_getNoASDU (IntPtr self);
static extern int ClientSVControlBlock_getNoASDU(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern PhyComAddress ClientSVControlBlock_getDstAddress (IntPtr self);
static extern PhyComAddress ClientSVControlBlock_getDstAddress(IntPtr self);
private IntPtr self;
private string objectReference;
private bool isDisposed = false;
public IntPtr Self { get => self;}
public IntPtr Self { get => self; }
internal SampledValuesControlBlock(IntPtr iedConnection, string objectReference)
{
self = ClientSVControlBlock_create (iedConnection, objectReference);
self = ClientSVControlBlock_create(iedConnection, objectReference);
this.objectReference = objectReference;
}
public string GetObjectReference ()
public string GetObjectReference()
{
return this.objectReference;
return objectReference;
}
public IedClientError GetLastComError()
{
return (IedClientError)ClientSVControlBlock_getLastComError (self);
return (IedClientError)ClientSVControlBlock_getLastComError(self);
}
public bool IsMulticast()
{
return ClientSVControlBlock_isMulticast (self);
return ClientSVControlBlock_isMulticast(self);
}
public bool GetResv()
{
return ClientSVControlBlock_getResv (self);
return ClientSVControlBlock_getResv(self);
}
public bool SetResv(bool value)
{
return ClientSVControlBlock_setResv (self, value);
return ClientSVControlBlock_setResv(self, value);
}
public bool GetSvEna()
{
return ClientSVControlBlock_getSvEna (self);
return ClientSVControlBlock_getSvEna(self);
}
public bool SetSvEna(bool value)
{
return ClientSVControlBlock_setSvEna (self, value);
return ClientSVControlBlock_setSvEna(self, value);
}
public string GetMsvID ()
public string GetMsvID()
{
IntPtr msvIdPtr = ClientSVControlBlock_getMsvID (self);
IntPtr msvIdPtr = ClientSVControlBlock_getMsvID(self);
return Marshal.PtrToStringAnsi (msvIdPtr);
return Marshal.PtrToStringAnsi(msvIdPtr);
}
public string GetDatSet ()
public string GetDatSet()
{
IntPtr datSetPtr = ClientSVControlBlock_getDatSet (self);
IntPtr datSetPtr = ClientSVControlBlock_getDatSet(self);
return Marshal.PtrToStringAnsi (datSetPtr);
return Marshal.PtrToStringAnsi(datSetPtr);
}
public UInt32 GetConfRev ()
public UInt32 GetConfRev()
{
return ClientSVControlBlock_getConfRev (self);
return ClientSVControlBlock_getConfRev(self);
}
public UInt16 GetSmpRate ()
public UInt16 GetSmpRate()
{
return ClientSVControlBlock_getSmpRate (self);
return ClientSVControlBlock_getSmpRate(self);
}
public SVOptions GetOptFlds ()
public SVOptions GetOptFlds()
{
return (SVOptions)ClientSVControlBlock_getOptFlds (self);
return (SVOptions)ClientSVControlBlock_getOptFlds(self);
}
public SmpMod GetSmpMod ()
public SmpMod GetSmpMod()
{
return (SmpMod)ClientSVControlBlock_getSmpMod (self);
return (SmpMod)ClientSVControlBlock_getSmpMod(self);
}
public int GetNoASDU ()
public int GetNoASDU()
{
return ClientSVControlBlock_getNoASDU (self);
return ClientSVControlBlock_getNoASDU(self);
}
public PhyComAddress GetDstAddress()
{
return ClientSVControlBlock_getDstAddress (self);
return ClientSVControlBlock_getDstAddress(self);
}
public void Dispose()
{
if (isDisposed == false) {
if (isDisposed == false)
{
isDisposed = true;
ClientSVControlBlock_destroy (self);
ClientSVControlBlock_destroy(self);
self = IntPtr.Zero;
}
}
~SampledValuesControlBlock()
{
Dispose ();
Dispose();
}
}

@ -1,7 +1,7 @@
/*
* SampledValuedSubscriber.cs
*
* Copyright 2017 Michael Zillgith
* Copyright 2017-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,9 +21,9 @@
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850
{
@ -41,7 +41,7 @@ namespace IEC61850
public class SVReceiver : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVReceiver_create ();
private static extern IntPtr SVReceiver_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_disableDestAddrCheck(IntPtr self);
@ -63,7 +63,7 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVReceiver_isRunning (IntPtr self);
private static extern bool SVReceiver_isRunning(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_destroy(IntPtr self);
@ -81,22 +81,22 @@ namespace IEC61850
public SVReceiver()
{
self = SVReceiver_create ();
self = SVReceiver_create();
}
public void SetInterfaceId(string interfaceId)
{
SVReceiver_setInterfaceId (self, interfaceId);
SVReceiver_setInterfaceId(self, interfaceId);
}
public void DisableDestAddrCheck()
{
SVReceiver_disableDestAddrCheck (self);
SVReceiver_disableDestAddrCheck(self);
}
public void EnableDestAddrCheck()
{
SVReceiver_enableDestAddrCheck (self);
SVReceiver_enableDestAddrCheck(self);
}
/// <summary>
@ -105,13 +105,13 @@ namespace IEC61850
/// <param name="subscriber">Subscriber.</param>
public void AddSubscriber(SVSubscriber subscriber)
{
SVReceiver_addSubscriber (self, subscriber.self);
SVReceiver_addSubscriber(self, subscriber.self);
}
public void RemoveSubscriber(SVSubscriber subscriber)
{
SVReceiver_removeSubscriber (self, subscriber.self);
SVReceiver_removeSubscriber(self, subscriber.self);
}
/// <summary>
@ -119,7 +119,7 @@ namespace IEC61850
/// </summary>
public void Start()
{
SVReceiver_start (self);
SVReceiver_start(self);
}
/// <summary>
@ -127,12 +127,12 @@ namespace IEC61850
/// </summary>
public void Stop()
{
SVReceiver_stop (self);
SVReceiver_stop(self);
}
public bool IsRunning()
{
return SVReceiver_isRunning (self);
return SVReceiver_isRunning(self);
}
/// <summary>
@ -145,16 +145,17 @@ namespace IEC61850
/// <see cref="IEC61850.SV.Subscriber.SVReceiver"/> was occupying.</remarks>
public void Dispose()
{
if (isDisposed == false) {
if (isDisposed == false)
{
isDisposed = true;
SVReceiver_destroy (self);
SVReceiver_destroy(self);
self = IntPtr.Zero;
}
}
~SVReceiver()
{
Dispose ();
Dispose();
}
}
@ -162,7 +163,7 @@ namespace IEC61850
/// <summary>
/// SV listener.
/// </summary>
public delegate void SVUpdateListener (SVSubscriber report, object parameter, SVSubscriberASDU asdu);
public delegate void SVUpdateListener(SVSubscriber report, object parameter, SVSubscriberASDU asdu);
/// <summary>
/// Sampled Values (SV) Subscriber
@ -174,7 +175,7 @@ namespace IEC61850
public class SVSubscriber : IDisposable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalSVUpdateListener (IntPtr subscriber, IntPtr parameter, IntPtr asdu);
private delegate void InternalSVUpdateListener(IntPtr subscriber, IntPtr parameter, IntPtr asdu);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVSubscriber_create([Out] byte[] ethAddr, UInt16 appID);
@ -197,16 +198,19 @@ namespace IEC61850
private event InternalSVUpdateListener internalListener = null;
private void internalSVUpdateListener (IntPtr subscriber, IntPtr parameter, IntPtr asdu)
private void internalSVUpdateListener(IntPtr subscriber, IntPtr parameter, IntPtr asdu)
{
try
{
try {
if (listener != null) {
if (listener != null)
{
listener(this, listenerParameter, new SVSubscriberASDU(asdu));
}
}
catch (Exception e) {
catch (Exception e)
{
// older versions of mono 2.10 (for linux?) cause this exception
Console.WriteLine(e.Message);
}
@ -214,34 +218,39 @@ namespace IEC61850
public SVSubscriber(byte[] ethAddr, UInt16 appID)
{
if (ethAddr == null) {
self = SVSubscriber_create (IntPtr.Zero, appID);
} else {
if (ethAddr == null)
{
self = SVSubscriber_create(IntPtr.Zero, appID);
}
else
{
if (ethAddr.Length != 6)
throw new ArgumentException ("ethAddr argument has to be of 6 byte size");
throw new ArgumentException("ethAddr argument has to be of 6 byte size");
self = SVSubscriber_create (ethAddr, appID);
self = SVSubscriber_create(ethAddr, appID);
}
}
public void SetListener(SVUpdateListener listener, object parameter)
{
this.listener = listener;
this.listenerParameter = parameter;
listenerParameter = parameter;
if (internalListener == null) {
internalListener = new InternalSVUpdateListener (internalSVUpdateListener);
if (internalListener == null)
{
internalListener = new InternalSVUpdateListener(internalSVUpdateListener);
SVSubscriber_setListener (self, internalListener, IntPtr.Zero);
SVSubscriber_setListener(self, internalListener, IntPtr.Zero);
}
}
public void Dispose()
{
if (isDisposed == false) {
if (isDisposed == false)
{
isDisposed = true;
SVSubscriber_destroy (self);
SVSubscriber_destroy(self);
self = IntPtr.Zero;
}
}
@ -325,114 +334,114 @@ namespace IEC61850
private IntPtr self;
internal SVSubscriberASDU (IntPtr self)
internal SVSubscriberASDU(IntPtr self)
{
this.self = self;
}
public UInt16 GetSmpCnt()
{
return SVSubscriber_ASDU_getSmpCnt (self);
return SVSubscriber_ASDU_getSmpCnt(self);
}
public string GetSvId()
{
return Marshal.PtrToStringAnsi (SVSubscriber_ASDU_getSvId(self));
return Marshal.PtrToStringAnsi(SVSubscriber_ASDU_getSvId(self));
}
public string GetDatSet()
{
return Marshal.PtrToStringAnsi (SVSubscriber_ASDU_getDatSet(self));
return Marshal.PtrToStringAnsi(SVSubscriber_ASDU_getDatSet(self));
}
public UInt32 GetConfRev()
{
return SVSubscriber_ASDU_getConfRev (self);
return SVSubscriber_ASDU_getConfRev(self);
}
public SmpMod GetSmpMod()
{
return (SmpMod) SVSubscriber_ASDU_getSmpMod (self);
return (SmpMod)SVSubscriber_ASDU_getSmpMod(self);
}
public UInt16 GetSmpRate()
{
return (UInt16)SVSubscriber_ASDU_getSmpRate (self);
return SVSubscriber_ASDU_getSmpRate(self);
}
public bool HasDatSet()
{
return SVSubscriber_ASDU_hasDatSet (self);
return SVSubscriber_ASDU_hasDatSet(self);
}
public bool HasRefrRm()
{
return SVSubscriber_ASDU_hasRefrTm (self);
return SVSubscriber_ASDU_hasRefrTm(self);
}
public bool HasSmpMod()
{
return SVSubscriber_ASDU_hasSmpMod (self);
return SVSubscriber_ASDU_hasSmpMod(self);
}
public bool HasSmpRate()
{
return SVSubscriber_ASDU_hasSmpRate (self);
return SVSubscriber_ASDU_hasSmpRate(self);
}
public UInt64 GetRefrTmAsMs()
{
return SVSubscriber_ASDU_getRefrTmAsMs (self);
return SVSubscriber_ASDU_getRefrTmAsMs(self);
}
public sbyte GetINT8(int index)
{
return SVSubscriber_ASDU_getINT8 (self, index);
return SVSubscriber_ASDU_getINT8(self, index);
}
public Int16 GetINT16(int index)
{
return SVSubscriber_ASDU_getINT16 (self, index);
return SVSubscriber_ASDU_getINT16(self, index);
}
public Int32 GetINT32(int index)
{
return SVSubscriber_ASDU_getINT32 (self, index);
return SVSubscriber_ASDU_getINT32(self, index);
}
public Int64 GetINT64(int index)
{
return SVSubscriber_ASDU_getINT64 (self, index);
return SVSubscriber_ASDU_getINT64(self, index);
}
public byte GetINT8U(int index)
{
return SVSubscriber_ASDU_getINT8U (self, index);
return SVSubscriber_ASDU_getINT8U(self, index);
}
public UInt16 GetINT16U(int index)
{
return SVSubscriber_ASDU_getINT16U (self, index);
return SVSubscriber_ASDU_getINT16U(self, index);
}
public UInt32 GetINT32U(int index)
{
return SVSubscriber_ASDU_getINT32U (self, index);
return SVSubscriber_ASDU_getINT32U(self, index);
}
public UInt64 GetINT64U(int index)
{
return SVSubscriber_ASDU_getINT64U (self, index);
return SVSubscriber_ASDU_getINT64U(self, index);
}
public float GetFLOAT32(int index)
{
return SVSubscriber_ASDU_getFLOAT32 (self, index);
return SVSubscriber_ASDU_getFLOAT32(self, index);
}
public double GetFLOAT64(int index)
{
return SVSubscriber_ASDU_getFLOAT64 (self, index);
return SVSubscriber_ASDU_getFLOAT64(self, index);
}
private struct PTimestamp
@ -446,16 +455,16 @@ namespace IEC61850
public Timestamp GetTimestamp(int index)
{
PTimestamp retVal = SVSubscriber_ASDU_getTimestamp (self, index);
PTimestamp retVal = SVSubscriber_ASDU_getTimestamp(self, index);
return new Timestamp (retVal.val);
return new Timestamp(retVal.val);
}
public Quality GetQuality(int index)
{
UInt16 qValue = SVSubscriber_ASDU_getQuality (self, index);
UInt16 qValue = SVSubscriber_ASDU_getQuality(self, index);
return new Quality (qValue);
return new Quality(qValue);
}
/// <summary>
@ -464,7 +473,7 @@ namespace IEC61850
/// <returns>The payload data size in byte</returns>
public int GetDataSize()
{
return SVSubscriber_ASDU_getDataSize (self);
return SVSubscriber_ASDU_getDataSize(self);
}
}
}

@ -21,14 +21,9 @@
* 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.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using IEC61850.Common;
using System.Security.Cryptography.X509Certificates;
/// <summary>
/// IEC 61850 API for the libiec61850 .NET wrapper library
@ -114,7 +109,7 @@ namespace IEC61850
{
if (isValid)
{
return (TLSConfigVersion)TLSConnection_getTLSVersion((IntPtr)self);
return (TLSConfigVersion)TLSConnection_getTLSVersion(self);
}
else
{
@ -136,7 +131,7 @@ namespace IEC61850
if (isValid)
{
IntPtr peerAddrBuf = Marshal.AllocHGlobal(130);
IntPtr peerAddrStr = TLSConnection_getPeerAddress(this.self, peerAddrBuf);
IntPtr peerAddrStr = TLSConnection_getPeerAddress(self, peerAddrBuf);
string peerAddr = null;
@ -331,8 +326,8 @@ namespace IEC61850
public void SetEventHandler(TLSEventHandler handler, object parameter)
{
this.eventHandler = handler;
this.eventHandlerParameter = parameter;
eventHandler = handler;
eventHandlerParameter = parameter;
if (internalTLSEventHandlerRef == null)
{

@ -8,6 +8,7 @@
using System;
using IEC61850.Server;
using IEC61850.Common;
using IEC61850;
using System.Threading;
using System.Net;
using static IEC61850.Server.IedServer;
@ -17,6 +18,7 @@ using IEC61850.Client;
using ReportControlBlock = IEC61850.Server.ReportControlBlock;
using IEC61850.Model;
using System.Data.Common;
using System.Security.Cryptography;
namespace server_access_control
{
@ -142,12 +144,23 @@ namespace server_access_control
/* Install handler to control access to control blocks (RCBs, LCBs, GoCBs, SVCBs, SGCBs)*/
bool ControlBlockAccessCallBack(object parameter, ClientConnection connection, ACSIClass acsiClass, LogicalDevice ld, LogicalNode ln, string objectName, string subObjectName, ControlBlockAccessType accessType)
{
string password = parameter as string;
object securityToken = connection.GetSecurityToken();
if(securityToken != null)
{
if ((securityToken as string == password))
Console.WriteLine("Correct securityToken");
else
Console.WriteLine("Incorrect securityToken");
}
Console.WriteLine(acsiClass.ToString() + " "+ accessType.ToString() + " access " + ld.GetName() + ln.GetName() +"/"+ objectName + "." + subObjectName + "\n");
return true;
}
iedServer.SetControlBlockAccessHandler(ControlBlockAccessCallBack, iedServer);
iedServer.SetControlBlockAccessHandler(ControlBlockAccessCallBack, "securityToken_password");
/* By default access to variables with FC=DC and FC=CF is not allowed.
* This allow to write to simpleIOGenericIO/GGIO1.NamPlt.vendor variable used
@ -332,6 +345,67 @@ namespace server_access_control
iedServer.SetSVCBHandler(sVCBEventHandler, sampledValuesControlBlock_1, null);
iedServer.SetSVCBHandler(sVCBEventHandler, sampledValuesControlBlock_2, null);
bool clientAuthenticator (object parameter, AcseAuthenticationParameter authParameter, object securityToken, IsoApplicationReference isoApplicationReference)
{
List<string> passwords = parameter as List<string>;
int aeQualifier = isoApplicationReference.GetAeQualifier();
ItuObjectIdentifier ituObjectIdentifier = isoApplicationReference.GetApTitle();
int arcCount = ituObjectIdentifier.GetArcCount();
ushort[] arc = ituObjectIdentifier.GetArcs();
Console.WriteLine("ACSE Authenticator:\n");
string appTitle = "";
for (int i = 0; i < arcCount; i++)
{
appTitle += arc[i];
if (i != (arcCount - 1))
appTitle += ".";
}
Console.WriteLine(" client ap-title: " + appTitle);
Console.WriteLine("\n client ae-qualifier: "+ aeQualifier + " \n");
IEC61850.AcseAuthenticationMechanism acseAuthenticationMechanism = authParameter.GetAuthMechanism();
if (acseAuthenticationMechanism == IEC61850.AcseAuthenticationMechanism.ACSE_AUTH_PASSWORD)
{
byte[] passArray = authParameter.GetPasswordByteArray();
int passwordLenght = passArray.Length;
string password = authParameter.GetPasswordString();
if (passwordLenght == passwords.First().Length)
{
if (password == passwords.First())
{
securityToken = passwords.First();
return true;
}
}
else if (passwordLenght == passwords[1].Length)
{
if (password == passwords[1])
{
securityToken = passwords[1];
return true;
}
}
}
return false;
}
List<string> passwords = new List<string>();
passwords.Add("user1@testpw");
passwords.Add("user2@testpw");
iedServer.SetAuthenticator(clientAuthenticator, passwords);
iedServer.Start(102);
if (iedServer.IsRunning())

@ -60,7 +60,7 @@ main(int argc, char** argv)
IsoConnectionParameters_setRemoteAddresses(parameters, remotePSelector, remoteSSelector, localTSelector);
IsoConnectionParameters_setLocalAddresses(parameters, localPSelector, localSSelector, remoteTSelector);
char* password = "top secret";
char* password = "user1@testpw";
/* use authentication */
AcseAuthenticationParameter auth = AcseAuthenticationParameter_create();
@ -84,6 +84,8 @@ main(int argc, char** argv)
printf("Failed to connect to %s:%i\n", hostname, tcpPort);
}
while (true);
IedConnection_destroy(con);
AcseAuthenticationParameter_destroy(auth);

@ -1,7 +1,7 @@
/*
* reporting.c
*
* Copyright 2013-2024 Michael Zillgith
* Copyright 2013-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*

@ -1,7 +1,7 @@
/*
* config_file_parser.c
*
* Copyright 2014-2024 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*

@ -1,7 +1,7 @@
/*
* asn1_ber_primitive_value.c
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -28,15 +28,17 @@
Asn1PrimitiveValue*
Asn1PrimitiveValue_create(int size)
{
Asn1PrimitiveValue* self = (Asn1PrimitiveValue*) GLOBAL_MALLOC(sizeof(Asn1PrimitiveValue));
Asn1PrimitiveValue* self = (Asn1PrimitiveValue*)GLOBAL_MALLOC(sizeof(Asn1PrimitiveValue));
if (self) {
if (self)
{
self->size = 1;
self->maxSize = size;
self->octets = (uint8_t*) GLOBAL_CALLOC(1, size);
self->octets = (uint8_t*)GLOBAL_CALLOC(1, size);
if (self->octets == NULL) {
if (self->octets == NULL)
{
GLOBAL_FREEMEM(self);
self = NULL;
}
@ -48,22 +50,24 @@ Asn1PrimitiveValue_create(int size)
Asn1PrimitiveValue*
Asn1PrimitiveValue_clone(Asn1PrimitiveValue* self)
{
Asn1PrimitiveValue* clone = (Asn1PrimitiveValue*) GLOBAL_MALLOC(sizeof(Asn1PrimitiveValue));
Asn1PrimitiveValue* clone = (Asn1PrimitiveValue*)GLOBAL_MALLOC(sizeof(Asn1PrimitiveValue));
if (clone) {
if (clone)
{
clone->size = self->size;
clone->maxSize = self->maxSize;
clone->octets = (uint8_t*) GLOBAL_MALLOC(self->maxSize);
clone->octets = (uint8_t*)GLOBAL_MALLOC(self->maxSize);
if (clone->octets) {
if (clone->octets)
{
memcpy(clone->octets, self->octets, clone->maxSize);
}
else {
else
{
GLOBAL_FREEMEM(clone);
clone = NULL;
}
}
return clone;
@ -72,7 +76,8 @@ Asn1PrimitiveValue_clone(Asn1PrimitiveValue* self)
bool
Asn1PrimitivaValue_compare(Asn1PrimitiveValue* self, Asn1PrimitiveValue* otherValue)
{
if (self->size == otherValue->size) {
if (self->size == otherValue->size)
{
if (memcmp(self->octets, otherValue->octets, self->size) == 0)
return true;
else
@ -97,7 +102,8 @@ Asn1PrimitiveValue_getMaxSize(Asn1PrimitiveValue* self)
void
Asn1PrimitiveValue_destroy(Asn1PrimitiveValue* self)
{
if (self) {
if (self)
{
GLOBAL_FREEMEM(self->octets);
GLOBAL_FREEMEM(self);
}

@ -1,7 +1,7 @@
/*
* ber_decoder.c
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -37,14 +37,18 @@ getIndefiniteLength(uint8_t* buffer, int bufPos, int maxBufPos, int depth, int m
int length = 0;
while (bufPos < maxBufPos) {
if ((buffer[bufPos] == 0) && ((bufPos + 1) < maxBufPos) && (buffer[bufPos+1] == 0)) {
while (bufPos < maxBufPos)
{
if ((buffer[bufPos] == 0) && ((bufPos + 1) < maxBufPos) && (buffer[bufPos + 1] == 0))
{
return length + 2;
}
else {
else
{
length++;
if ((buffer[bufPos++] & 0x1f) == 0x1f) {
if ((buffer[bufPos++] & 0x1f) == 0x1f)
{
/* handle extended tags */
bufPos++;
length++;
@ -74,17 +78,21 @@ BerDecoder_decodeLengthRecursive(uint8_t* buffer, int* length, int bufPos, int m
uint8_t len1 = buffer[bufPos++];
if (len1 & 0x80) {
if (len1 & 0x80)
{
int lenLength = len1 & 0x7f;
if (lenLength == 0) { /* indefinite length form */
if (lenLength == 0)
{ /* indefinite length form */
*length = getIndefiniteLength(buffer, bufPos, maxBufPos, depth, maxDepth);
}
else {
else
{
*length = 0;
int i;
for (i = 0; i < lenLength; i++) {
for (i = 0; i < lenLength; i++)
{
if (bufPos >= maxBufPos)
return -1;
@ -95,18 +103,15 @@ BerDecoder_decodeLengthRecursive(uint8_t* buffer, int* length, int bufPos, int m
*length += buffer[bufPos++];
}
}
}
else {
else
{
*length = len1;
}
if (*length < 0)
return -1;
if (*length > maxBufPos)
return -1;
if (bufPos + (*length) > maxBufPos)
return -1;
@ -126,8 +131,12 @@ BerDecoder_decodeString(uint8_t* buffer, int strlen, int bufPos, int maxBufPos)
return NULL;
char* string = (char*) GLOBAL_MALLOC(strlen + 1);
if (string)
{
memcpy(string, buffer + bufPos, strlen);
string[strlen] = 0;
}
return string;
}
@ -138,7 +147,8 @@ BerDecoder_decodeUint32(uint8_t* buffer, int intLen, int bufPos)
uint32_t value = 0;
int i;
for (i = 0; i < intLen; i++) {
for (i = 0; i < intLen; i++)
{
value <<= 8;
value += buffer[bufPos + i];
}
@ -159,7 +169,8 @@ BerDecoder_decodeInt32(uint8_t* buffer, int intlen, int bufPos)
else
value = 0;
for (i = 0; i < intlen; i++) {
for (i = 0; i < intlen; i++)
{
value <<= 8;
value += buffer[bufPos + i];
}
@ -171,18 +182,20 @@ float
BerDecoder_decodeFloat(uint8_t* buffer, int bufPos)
{
float value;
uint8_t* valueBuf = (uint8_t*) &value;
uint8_t* valueBuf = (uint8_t*)&value;
int i;
bufPos += 1; /* skip exponentWidth field */
#if (ORDER_LITTLE_ENDIAN == 1)
for (i = 3; i >= 0; i--) {
for (i = 3; i >= 0; i--)
{
valueBuf[i] = buffer[bufPos++];
}
#else
for (i = 0; i < 4; i++) {
for (i = 0; i < 4; i++)
{
valueBuf[i] = buffer[bufPos++];
}
#endif
@ -194,18 +207,20 @@ double
BerDecoder_decodeDouble(uint8_t* buffer, int bufPos)
{
double value;
uint8_t* valueBuf = (uint8_t*) &value;
uint8_t* valueBuf = (uint8_t*)&value;
int i;
bufPos += 1; /* skip exponentWidth field */
#if (ORDER_LITTLE_ENDIAN == 1)
for (i = 7; i >= 0; i--) {
for (i = 7; i >= 0; i--)
{
valueBuf[i] = buffer[bufPos++];
}
#else
for (i = 0; i < 8; i++) {
for (i = 0; i < 8; i++)
{
valueBuf[i] = buffer[bufPos++];
}
#endif
@ -214,7 +229,8 @@ BerDecoder_decodeDouble(uint8_t* buffer, int bufPos)
}
bool
BerDecoder_decodeBoolean(uint8_t* buffer, int bufPos) {
BerDecoder_decodeBoolean(uint8_t* buffer, int bufPos)
{
if (buffer[bufPos] != 0)
return true;
else
@ -233,7 +249,8 @@ BerDecoder_decodeOID(uint8_t* buffer, int bufPos, int length, ItuObjectIdentifie
oid->arc[i] = 0;
/* parse first two arcs */
if (length > 0) {
if (length > 0)
{
oid->arc[0] = buffer[bufPos] / 40;
oid->arc[1] = buffer[bufPos] % 40;
@ -242,8 +259,9 @@ BerDecoder_decodeOID(uint8_t* buffer, int bufPos, int length, ItuObjectIdentifie
}
/* parse remaining arcs */
while ((bufPos - startPos < length) && (currentArc < 10)) {
oid->arc[currentArc] = oid->arc[currentArc]<<7;
while ((bufPos - startPos < length) && (currentArc < 10))
{
oid->arc[currentArc] = oid->arc[currentArc] << 7;
if (buffer[bufPos] < 0x80)
oid->arc[currentArc++] += buffer[bufPos];

@ -1,7 +1,7 @@
/*
* ber_integer.c
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -25,7 +25,7 @@
#include "ber_integer.h"
#include "ber_encoder.h"
static int
static bool
setIntegerValue(Asn1PrimitiveValue* self, uint8_t* valueBuffer, int bufferSize)
{
#if (ORDER_LITTLE_ENDIAN == 1)
@ -34,13 +34,15 @@ setIntegerValue(Asn1PrimitiveValue* self, uint8_t* valueBuffer, int bufferSize)
int size = BerEncoder_compressInteger(valueBuffer, bufferSize);
if (size <= self->maxSize) {
if (size <= self->maxSize)
{
self->size = size;
memcpy(self->octets, valueBuffer, size);
return 1;
return true;
}
else
return 0;
return false;
}
Asn1PrimitiveValue*
@ -61,7 +63,8 @@ BerInteger_createFromBuffer(uint8_t* buf, int size)
Asn1PrimitiveValue* self = Asn1PrimitiveValue_create(maxSize);
if (self) {
if (self)
{
memcpy(self->octets, buf, size);
self->size = size;
@ -70,21 +73,22 @@ BerInteger_createFromBuffer(uint8_t* buf, int size)
return self;
}
int
bool
BerInteger_setFromBerInteger(Asn1PrimitiveValue* self, Asn1PrimitiveValue* value)
{
if (self->maxSize >= value->size) {
if (self->maxSize >= value->size)
{
self->size = value->size;
memcpy(self->octets, value->octets, value->size);
return 1;
return true;
}
else
return 0;
return false;
}
int
bool
BerInteger_setInt32(Asn1PrimitiveValue* self, int32_t value)
{
int32_t valueCopy = value;
@ -98,14 +102,15 @@ BerInteger_createFromInt32(int32_t value)
{
Asn1PrimitiveValue* asn1Value = BerInteger_createInt32();
if (asn1Value) {
if (asn1Value)
{
BerInteger_setInt32(asn1Value, value);
}
return asn1Value;
}
int
bool
BerInteger_setUint16(Asn1PrimitiveValue* self, uint16_t value)
{
uint16_t valueCopy = value;
@ -130,7 +135,7 @@ BerInteger_setUint16(Asn1PrimitiveValue* self, uint16_t value)
return setIntegerValue(self, byteBuffer, sizeof(byteBuffer));
}
int
bool
BerInteger_setUint8(Asn1PrimitiveValue* self, uint8_t value)
{
uint8_t valueCopy = value;
@ -139,7 +144,7 @@ BerInteger_setUint8(Asn1PrimitiveValue* self, uint8_t value)
return setIntegerValue(self, valueBuffer, sizeof(value));
}
int
bool
BerInteger_setUint32(Asn1PrimitiveValue* self, uint32_t value)
{
uint32_t valueCopy = value;
@ -169,7 +174,8 @@ BerInteger_createFromUint32(uint32_t value)
{
Asn1PrimitiveValue* asn1Value = BerInteger_createInt32();
if (asn1Value) {
if (asn1Value)
{
BerInteger_setUint32(asn1Value, value);
}
@ -182,7 +188,7 @@ BerInteger_createInt64()
return Asn1PrimitiveValue_create(9);
}
int
bool
BerInteger_setInt64(Asn1PrimitiveValue* self, int64_t value)
{
int64_t valueCopy = value;
@ -196,7 +202,8 @@ BerInteger_createFromInt64(int64_t value)
{
Asn1PrimitiveValue* asn1Value = BerInteger_createInt64();
if (asn1Value) {
if (asn1Value)
{
BerInteger_setInt64(asn1Value, value);
}
@ -244,4 +251,3 @@ BerInteger_toInt64(Asn1PrimitiveValue* self, int64_t* nativeValue)
for (i = 0; i < self->size; i++)
*nativeValue = (*nativeValue << 8) | buf[i];
}

@ -91,11 +91,31 @@ AcseAuthenticationParameter_destroy(AcseAuthenticationParameter self);
LIB61850_API void
AcseAuthenticationParameter_setAuthMechanism(AcseAuthenticationParameter self, AcseAuthenticationMechanism mechanism);
LIB61850_API AcseAuthenticationMechanism
AcseAuthenticationParameter_getAuthMechanism(AcseAuthenticationParameter self);
LIB61850_API void
AcseAuthenticationParameter_setPassword(AcseAuthenticationParameter self, char* password);
LIB61850_API const char*
AcseAuthenticationParameter_getPassword(AcseAuthenticationParameter self);
/**
LIB61850_API int
AcseAuthenticationParameter_getPasswordLength(AcseAuthenticationParameter self);
LIB61850_API int
IsoApplicationReference_getAeQualifier(IsoApplicationReference self);
LIB61850_API const ItuObjectIdentifier*
IsoApplicationReference_getApTitle(const IsoApplicationReference* self);
LIB61850_API int
ItuObjectIdentifier_getArcCount(ItuObjectIdentifier* self);
LIB61850_API const uint16_t*
ItuObjectIdentifier_getArc(ItuObjectIdentifier* self);
/**
* \brief Callback function to authenticate a client
*
* \param parameter user provided parameter - set when user registers the authenticator

@ -1,7 +1,7 @@
/*
* ber_integer.h
*
* Copyright 2013-2018 Michael Zillgith
* Copyright 2013-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -36,22 +36,22 @@ BerInteger_createFromBuffer(uint8_t* buf, int size);
LIB61850_INTERNAL Asn1PrimitiveValue*
BerInteger_createInt32(void);
LIB61850_INTERNAL int
LIB61850_INTERNAL bool
BerInteger_setFromBerInteger(Asn1PrimitiveValue* self, Asn1PrimitiveValue* value);
LIB61850_INTERNAL int
LIB61850_INTERNAL bool
BerInteger_setInt32(Asn1PrimitiveValue* self, int32_t value);
LIB61850_INTERNAL Asn1PrimitiveValue*
BerInteger_createFromInt32(int32_t value);
LIB61850_INTERNAL int
LIB61850_INTERNAL bool
BerInteger_setUint8(Asn1PrimitiveValue* self, uint8_t value);
LIB61850_INTERNAL int
LIB61850_INTERNAL bool
BerInteger_setUint16(Asn1PrimitiveValue* self, uint16_t value);
LIB61850_INTERNAL int
LIB61850_INTERNAL bool
BerInteger_setUint32(Asn1PrimitiveValue* self, uint32_t value);
LIB61850_INTERNAL Asn1PrimitiveValue*
@ -63,7 +63,7 @@ BerInteger_createFromInt64(int64_t value);
LIB61850_INTERNAL Asn1PrimitiveValue*
BerInteger_createInt64(void);
LIB61850_INTERNAL int
LIB61850_INTERNAL bool
BerInteger_setInt64(Asn1PrimitiveValue* self, int64_t value);
LIB61850_INTERNAL void

@ -57,12 +57,76 @@ AcseAuthenticationParameter_setPassword(AcseAuthenticationParameter self, char*
self->value.password.passwordLength = strlen(password);
}
/* TODO
->One function returning as string and another as by array*/
const char*
AcseAuthenticationParameter_getPassword(AcseAuthenticationParameter self)
{
if (self == NULL)
return NULL;
if (self->mechanism != ACSE_AUTH_PASSWORD)
return NULL;
return (char*)self->value.password.octetString;
}
int
AcseAuthenticationParameter_getPasswordLength(AcseAuthenticationParameter self)
{
if (self == NULL)
return 0;
if (self->mechanism != ACSE_AUTH_PASSWORD)
return 0;
return self->value.password.passwordLength;
}
void
AcseAuthenticationParameter_setAuthMechanism(AcseAuthenticationParameter self, AcseAuthenticationMechanism mechanism)
{
self->mechanism = mechanism;
}
AcseAuthenticationMechanism
AcseAuthenticationParameter_getAuthMechanism(AcseAuthenticationParameter self)
{
return self->mechanism;
}
LIB61850_API int
IsoApplicationReference_getAeQualifier(IsoApplicationReference self)
{
return self.aeQualifier;
}
LIB61850_API const ItuObjectIdentifier*
IsoApplicationReference_getApTitle(const IsoApplicationReference* self)
{
if (self == NULL)
return NULL;
return &(self->apTitle);
}
LIB61850_API int
ItuObjectIdentifier_getArcCount(ItuObjectIdentifier* self)
{
if (self == NULL)
return NULL;
return self->arcCount;
}
LIB61850_API const uint16_t*
ItuObjectIdentifier_getArc(ItuObjectIdentifier* self)
{
if (self == NULL)
return NULL;
return self->arc;
}
IsoConnectionParameters
IsoConnectionParameters_create()
{

@ -1,7 +1,7 @@
/*
* mms_server.c
*
* Copyright 2013-2024 Michael Zillgith
* Copyright 2013-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*

Loading…
Cancel
Save