diff --git a/dotnet/IEC61850forCSharp/AcseAuthenticationParameter.cs b/dotnet/IEC61850forCSharp/AcseAuthenticationParameter.cs new file mode 100644 index 00000000..056be620 --- /dev/null +++ b/dotnet/IEC61850forCSharp/AcseAuthenticationParameter.cs @@ -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 . + * + * 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 +{ + /// + /// Authentication mechanism used by AcseAuthenticator + /// + 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(); + + 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; + } + } +} diff --git a/dotnet/IEC61850forCSharp/AssemblyInfo.cs b/dotnet/IEC61850forCSharp/AssemblyInfo.cs index f5d02ba2..d26e3bdf 100644 --- a/dotnet/IEC61850forCSharp/AssemblyInfo.cs +++ b/dotnet/IEC61850forCSharp/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/dotnet/IEC61850forCSharp/Control.cs b/dotnet/IEC61850forCSharp/Control.cs index 97a3d767..0d3bf940 100644 --- a/dotnet/IEC61850forCSharp/Control.cs +++ b/dotnet/IEC61850forCSharp/Control.cs @@ -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 { +{ + // IEC 61850 common API parts (used by client and server API) + namespace Common + { /// /// 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 /// /// Originator category /// - 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 */ @@ -70,33 +71,33 @@ namespace IEC61850 MAINTENANCE = 7, /** Status change occurred without control action (for example external trip of a circuit breaker or failure inside the breaker) */ PROCESS = 8 + } + } + + namespace Client + { + [StructLayout(LayoutKind.Sequential)] + internal struct LastApplErrorInternal + { + public int ctlNum; + public int error; + public int addCause; + } + + public class LastApplError + { + public int ctlNum; + public int error; + public ControlAddCause addCause; + + + internal LastApplError(LastApplErrorInternal lastApplError) + { + addCause = (ControlAddCause)lastApplError.addCause; + error = lastApplError.error; + ctlNum = lastApplError.ctlNum; + } } - } - - namespace Client - { - [StructLayout(LayoutKind.Sequential)] - internal struct LastApplErrorInternal - { - public int ctlNum; - public int error; - public int addCause; - } - - public class LastApplError - { - public int ctlNum; - public int error; - public ControlAddCause addCause; - - - internal LastApplError (LastApplErrorInternal lastApplError) - { - this.addCause = (ControlAddCause) lastApplError.addCause; - this.error = lastApplError.error; - this.ctlNum = lastApplError.ctlNum; - } - } public enum ControlActionType { @@ -108,37 +109,37 @@ namespace IEC61850 /// /// Control object. /// - public class ControlObject : IDisposable - { - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern LastApplErrorInternal ControlObjectClient_getLastApplError(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr ControlObjectClient_create(string objectReference, IntPtr connection); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void ControlObjectClient_destroy(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern int ControlObjectClient_getControlModel(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern int ControlObjectClient_getCtlValType(IntPtr self); + public class ControlObject : IDisposable + { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern LastApplErrorInternal ControlObjectClient_getLastApplError(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr ControlObjectClient_create(string objectReference, IntPtr connection); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void ControlObjectClient_destroy(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern int ControlObjectClient_getControlModel(IntPtr self); + + [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)] - private static extern bool ControlObjectClient_operate(IntPtr self, IntPtr ctlVal, UInt64 operTime); + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool ControlObjectClient_operate(IntPtr self, IntPtr ctlVal, UInt64 operTime); /// /// Handler for asynchronous control actions (select, operate, cancel) /// - public delegate void ControlActionHandler (UInt32 invokeId, Object parameter, IedClientError error, ControlActionType type, bool success); + 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, @@ -169,53 +170,53 @@ namespace IEC61850 private static extern bool ControlObjectClient_cancel(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void ControlObjectClient_setOrigin(IntPtr self, string orIdent, int orCat); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void ControlObjectClient_setInterlockCheck(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void ControlObjectClient_setSynchroCheck(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void ControlObjectClient_setTestMode(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value); + private static extern void ControlObjectClient_setOrigin(IntPtr self, string orIdent, int orCat); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - 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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void ControlObjectClient_setInterlockCheck(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value); - private IedConnection iedConnection; - private IntPtr self; - - private CommandTerminationHandler commandTerminationHandler = null; - private Object commandTerminationHandlerParameter = null; - - private void MyCommandTerminationHandler (IntPtr paramter, IntPtr controlClient) - { - if (commandTerminationHandler != null) - commandTerminationHandler(commandTerminationHandlerParameter, this); - } - - private InternalCommandTerminationHandler intCommandTerminationHandler; - - internal ControlObject (string objectReference, IntPtr connection, IedConnection iedConnection) - { - this.iedConnection = iedConnection; - - this.self = ControlObjectClient_create(objectReference, connection); - - if (this.self == System.IntPtr.Zero) - throw new IedConnectionException("Control object not found", 0); - - intCommandTerminationHandler = new InternalCommandTerminationHandler (MyCommandTerminationHandler); - - ControlObjectClient_setCommandTerminationHandler(self, intCommandTerminationHandler, self); - } + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void ControlObjectClient_setSynchroCheck(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void ControlObjectClient_setTestMode(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + 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); + + private IedConnection iedConnection; + private IntPtr self; + + private CommandTerminationHandler commandTerminationHandler = null; + private Object commandTerminationHandlerParameter = null; + + private void MyCommandTerminationHandler(IntPtr paramter, IntPtr controlClient) + { + if (commandTerminationHandler != null) + commandTerminationHandler(commandTerminationHandlerParameter, this); + } + + private InternalCommandTerminationHandler intCommandTerminationHandler; + + internal ControlObject(string objectReference, IntPtr connection, IedConnection iedConnection) + { + this.iedConnection = iedConnection; + + self = ControlObjectClient_create(objectReference, connection); + + if (self == System.IntPtr.Zero) + throw new IedConnectionException("Control object not found", 0); + + intCommandTerminationHandler = new InternalCommandTerminationHandler(MyCommandTerminationHandler); + + ControlObjectClient_setCommandTerminationHandler(self, intCommandTerminationHandler, self); + } /// /// Gets the control model. @@ -223,23 +224,23 @@ namespace IEC61850 /// /// The control model. /// - public ControlModel GetControlModel () - { - ControlModel controlModel = (ControlModel) ControlObjectClient_getControlModel(self); - - return controlModel; - } - - /// - /// Get the type of ctlVal. - /// - /// MmsType required for the ctlVal value. - public MmsType GetCtlValType () - { - MmsType ctlValType = (MmsType) ControlObjectClient_getCtlValType (self); - - return ctlValType; - } + public ControlModel GetControlModel() + { + ControlModel controlModel = (ControlModel)ControlObjectClient_getControlModel(self); + + return controlModel; + } + + /// + /// Get the type of ctlVal. + /// + /// MmsType required for the ctlVal value. + public MmsType GetCtlValType() + { + MmsType ctlValType = (MmsType)ControlObjectClient_getCtlValType(self); + + return ctlValType; + } /// /// Sets the origin parameter used by control commands. @@ -250,18 +251,20 @@ namespace IEC61850 /// /// Originator category. /// - 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); } /// /// Gets the error code of the last synchronous control action (operate, select, select-with-value, cancel) /// /// error code. - public IedClientError LastError { - get { - return (IedClientError)ControlObjectClient_getLastError (self); + public IedClientError LastError + { + get + { + return (IedClientError)ControlObjectClient_getLastError(self); } } @@ -270,10 +273,10 @@ namespace IEC61850 /// /// the new value of the control /// true when the operation has been successful, false otherwise - public bool Operate (bool ctlVal) - { - return Operate (ctlVal, 0); - } + public bool Operate(bool ctlVal) + { + return Operate(ctlVal, 0); + } /// /// Operate the control with the specified control value (time activated control). @@ -281,22 +284,22 @@ namespace IEC61850 /// the new value of the control /// the time when the operation will be executed /// true when the operation has been successful, false otherwise - public bool Operate (bool ctlVal, UInt64 operTime) - { - MmsValue value = new MmsValue(ctlVal); - - return Operate (value, operTime); - } + public bool Operate(bool ctlVal, UInt64 operTime) + { + MmsValue value = new MmsValue(ctlVal); + + return Operate(value, operTime); + } /// /// Operate the control with the specified control value. /// /// the new value of the control /// true when the operation has been successful, false otherwise - public bool Operate (float ctlVal) - { - return Operate (ctlVal, 0); - } + public bool Operate(float ctlVal) + { + return Operate(ctlVal, 0); + } /// /// Operate the control with the specified control value (time activated control). @@ -304,22 +307,22 @@ namespace IEC61850 /// the new value of the control /// the time when the operation will be executed /// true when the operation has been successful, false otherwise - public bool Operate (float ctlVal, UInt64 operTime) - { - MmsValue value = new MmsValue(ctlVal); - - return Operate (value, operTime); - } + public bool Operate(float ctlVal, UInt64 operTime) + { + MmsValue value = new MmsValue(ctlVal); + + return Operate(value, operTime); + } /// /// Operate the control with the specified control value. /// /// the new value of the control /// true when the operation has been successful, false otherwise - public bool Operate (int ctlVal) - { - return Operate (ctlVal, 0); - } + public bool Operate(int ctlVal) + { + return Operate(ctlVal, 0); + } /// /// Operate the control with the specified control value (time activated control). @@ -327,22 +330,22 @@ namespace IEC61850 /// the new value of the control /// the time when the operation will be executed /// true when the operation has been successful, false otherwise - public bool Operate (int ctlVal, UInt64 operTime) - { - MmsValue value = new MmsValue(ctlVal); - - return Operate (value, operTime); - } + public bool Operate(int ctlVal, UInt64 operTime) + { + MmsValue value = new MmsValue(ctlVal); + + return Operate(value, operTime); + } /// /// Operate the control with the specified control value. /// /// the new value of the control /// true when the operation has been successful, false otherwise - public bool Operate (MmsValue ctlVal) - { - return Operate (ctlVal, 0); - } + public bool Operate(MmsValue ctlVal) + { + return Operate(ctlVal, 0); + } /// /// Operate the control with the specified control value (time activated control). @@ -350,18 +353,18 @@ namespace IEC61850 /// the new value of the control /// the time when the operation will be executed /// true when the operation has been successful, false otherwise - public bool Operate (MmsValue ctlVal, UInt64 operTime) - { - return ControlObjectClient_operate(self, ctlVal.valueReference, 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); - Tuple callbackInfo = handle.Target as Tuple; + Tuple callbackInfo = handle.Target as Tuple; ControlActionHandler handler = callbackInfo.Item1; object handlerParameter = callbackInfo.Item2; @@ -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,11 +385,11 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 OperateAsync (bool ctlVal, ControlActionHandler handler, object parameter) + public UInt32 OperateAsync(bool ctlVal, ControlActionHandler handler, object parameter) { - return OperateAsync (ctlVal, 0, handler, parameter); - } - + return OperateAsync(ctlVal, 0, handler, parameter); + } + /// /// Operate the control with the specified control value (time activated control). /// @@ -396,13 +399,13 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 OperateAsync (bool ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter) + 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); + } + /// /// Operate the control with the specified control value. /// @@ -411,11 +414,11 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 OperateAsync (float ctlVal, ControlActionHandler handler, object parameter) + public UInt32 OperateAsync(float ctlVal, ControlActionHandler handler, object parameter) { - return OperateAsync (ctlVal, 0, handler, parameter); - } - + return OperateAsync(ctlVal, 0, handler, parameter); + } + /// /// Operate the control with the specified control value (time activated control). /// @@ -425,13 +428,13 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 OperateAsync (float ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter) + 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); + } + /// /// Operate the control with the specified control value. /// @@ -440,9 +443,9 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 OperateAsync (int ctlVal, ControlActionHandler handler, object parameter) + public UInt32 OperateAsync(int ctlVal, ControlActionHandler handler, object parameter) { - return OperateAsync (ctlVal, 0, handler, parameter); + return OperateAsync(ctlVal, 0, handler, parameter); } /// @@ -454,9 +457,9 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 OperateAsync (int ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter) + public UInt32 OperateAsync(int ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter) { - return OperateAsync (ctlVal, operTime, handler, parameter); + return OperateAsync(ctlVal, operTime, handler, parameter); } /// @@ -467,9 +470,9 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 OperateAsync (MmsValue ctlVal, ControlActionHandler handler, object parameter) + public UInt32 OperateAsync(MmsValue ctlVal, ControlActionHandler handler, object parameter) { - return OperateAsync (ctlVal, 0, handler, parameter); + return OperateAsync(ctlVal, 0, handler, parameter); } /// @@ -481,7 +484,7 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 OperateAsync (MmsValue ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter) + public UInt32 OperateAsync(MmsValue ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter) { int error; @@ -507,7 +510,7 @@ namespace IEC61850 /// Select the control object. /// /// true when the selection has been successful, false otherwise - public bool Select () + public bool Select() { return ControlObjectClient_select(self); } @@ -546,7 +549,7 @@ namespace IEC61850 /// /// the value to be checked. /// true when the selection has been successful, false otherwise - 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. /// /// true when the selection has been successful, false otherwise - 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. /// /// true when the selection has been successful, false otherwise - 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. /// /// true when the selection has been successful, false otherwise - public bool SelectWithValue (float ctlVal) + public bool SelectWithValue(float ctlVal) { return SelectWithValue(new MmsValue(ctlVal)); } @@ -595,7 +598,7 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 SelectWithValueAsync (bool ctlVal, ControlActionHandler handler, object parameter) + public UInt32 SelectWithValueAsync(bool ctlVal, ControlActionHandler handler, object parameter) { return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter); } @@ -608,7 +611,7 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 SelectWithValueAsync (int ctlVal, ControlActionHandler handler, object parameter) + public UInt32 SelectWithValueAsync(int ctlVal, ControlActionHandler handler, object parameter) { return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter); } @@ -621,11 +624,11 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 SelectWithValueAsync (float ctlVal, ControlActionHandler handler, object parameter) + public UInt32 SelectWithValueAsync(float ctlVal, ControlActionHandler handler, object parameter) { return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter); - } - + } + /// /// Send a select with value command for generic MmsValue instances - asynchronous version /// @@ -634,7 +637,7 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public UInt32 SelectWithValueAsync (MmsValue ctlVal, ControlActionHandler handler, object parameter) + public UInt32 SelectWithValueAsync(MmsValue ctlVal, ControlActionHandler handler, object parameter) { int error; @@ -664,7 +667,7 @@ namespace IEC61850 /// User provided callback parameter. Will be passed to the callback function /// the invoke ID of the sent request /// This exception is thrown if there is a connection or service error - public bool Cancel () + public bool Cancel() { return ControlObjectClient_cancel(self); } @@ -698,90 +701,93 @@ namespace IEC61850 /// Enables the synchro check for operate commands /// [Obsolete("use SetSynchroCheck instead")] - public void EnableSynchroCheck () - { - ControlObjectClient_setSynchroCheck (self, true); + public void EnableSynchroCheck() + { + ControlObjectClient_setSynchroCheck(self, true); } /// /// Enables the interlock check for operate and select commands /// - [Obsolete("use SetInterlockCheck instead")] - public void EnableInterlockCheck () - { - ControlObjectClient_setInterlockCheck (self, true); - } - - /// - /// Sets the value of the interlock check flag for operate and select commands - /// - public void SetInterlockCheck (bool value) - { - ControlObjectClient_setInterlockCheck (self, value); - } - - /// - /// Sets the value of the synchro check flag for operate command - /// - public void SetSynchroCheck (bool value) - { - ControlObjectClient_setSynchroCheck (self, value); - } - - /// - /// Sets the value of the test flag for the operate command - /// - public void SetTestMode (bool value) - { - ControlObjectClient_setTestMode (self, value); - } - - /// - /// Gets the last received LastApplError (Additional Cause Diagnostics) value. - /// - /// - /// The last appl error. - /// - public LastApplError GetLastApplError () - { - LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(self); - - return new LastApplError(lastApplError); - } - - /// - /// Sets the command termination handler. - /// - /// - /// the handler (delegate) that is invoked when a CommandTerminationMessage is received. - /// - /// - /// Parameter. - /// - public void SetCommandTerminationHandler (CommandTerminationHandler handler, Object parameter) - { - this.commandTerminationHandler = handler; - this.commandTerminationHandlerParameter = parameter; - } - - protected virtual void Dispose(bool disposing) { - if (this.self != System.IntPtr.Zero) { - ControlObjectClient_destroy (self); - this.self = System.IntPtr.Zero; - } - } - - public void Dispose() { - Dispose (true); - } - - ~ControlObject() - { - Dispose (false); - } - } - - } + [Obsolete("use SetInterlockCheck instead")] + public void EnableInterlockCheck() + { + ControlObjectClient_setInterlockCheck(self, true); + } + + /// + /// Sets the value of the interlock check flag for operate and select commands + /// + public void SetInterlockCheck(bool value) + { + ControlObjectClient_setInterlockCheck(self, value); + } + + /// + /// Sets the value of the synchro check flag for operate command + /// + public void SetSynchroCheck(bool value) + { + ControlObjectClient_setSynchroCheck(self, value); + } + + /// + /// Sets the value of the test flag for the operate command + /// + public void SetTestMode(bool value) + { + ControlObjectClient_setTestMode(self, value); + } + + /// + /// Gets the last received LastApplError (Additional Cause Diagnostics) value. + /// + /// + /// The last appl error. + /// + public LastApplError GetLastApplError() + { + LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(self); + + return new LastApplError(lastApplError); + } + + /// + /// Sets the command termination handler. + /// + /// + /// the handler (delegate) that is invoked when a CommandTerminationMessage is received. + /// + /// + /// Parameter. + /// + public void SetCommandTerminationHandler(CommandTerminationHandler handler, Object parameter) + { + commandTerminationHandler = handler; + commandTerminationHandlerParameter = parameter; + } + + protected virtual void Dispose(bool disposing) + { + if (self != System.IntPtr.Zero) + { + ControlObjectClient_destroy(self); + self = System.IntPtr.Zero; + } + } + + public void Dispose() + { + Dispose(true); + } + + ~ControlObject() + { + Dispose(false); + } + } + + } } diff --git a/dotnet/IEC61850forCSharp/DataSet.cs b/dotnet/IEC61850forCSharp/DataSet.cs index d7304bc9..29e61eba 100644 --- a/dotnet/IEC61850forCSharp/DataSet.cs +++ b/dotnet/IEC61850forCSharp/DataSet.cs @@ -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 diff --git a/dotnet/IEC61850forCSharp/GooseControlBlock.cs b/dotnet/IEC61850forCSharp/GooseControlBlock.cs index 1e91d6fe..a2a7175c 100644 --- a/dotnet/IEC61850forCSharp/GooseControlBlock.cs +++ b/dotnet/IEC61850forCSharp/GooseControlBlock.cs @@ -1,7 +1,7 @@ /* * GooseControlBlock.cs * - * Copyright 2017 Michael Zillgith + * Copyright 2017-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -20,270 +20,270 @@ * * 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 - { + namespace Client + { + + public class GooseControlBlock : IDisposable + { + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientGooseControlBlock_create(string dataAttributeReference); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientGooseControlBlock_destroy(IntPtr self); - public class GooseControlBlock : IDisposable { - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientGooseControlBlock_create (string dataAttributeReference); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr IedConnection_getGoCBValues(IntPtr connection, out int error, string rcbReference, IntPtr updateRcb); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientGooseControlBlock_destroy(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void IedConnection_setGoCBValues(IntPtr connection, out int error, IntPtr rcb, UInt32 parametersMask, [MarshalAs(UnmanagedType.I1)] bool singleRequest); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr IedConnection_getGoCBValues (IntPtr connection, out int error, string rcbReference, IntPtr updateRcb); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool ClientGooseControlBlock_getGoEna(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientGooseControlBlock_setGoEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna); - [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); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientGooseControlBlock_getGoID (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientGooseControlBlock_setGoID(IntPtr self, string goId); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientGooseControlBlock_setGoID (IntPtr self, string goId); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientGooseControlBlock_getDatSet(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientGooseControlBlock_getDatSet (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientGooseControlBlock_setDatSet(IntPtr self, string datSet); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientGooseControlBlock_setDatSet (IntPtr self, string datSet); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 ClientGooseControlBlock_getConfRev(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 ClientGooseControlBlock_getConfRev (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool ClientGooseControlBlock_getNdsComm(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - static extern bool ClientGooseControlBlock_getNdsComm (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 ClientGooseControlBlock_getMinTime(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 ClientGooseControlBlock_getMinTime (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 ClientGooseControlBlock_getMaxTime(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 ClientGooseControlBlock_getMaxTime (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool ClientGooseControlBlock_getFixedOffs(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - static extern bool ClientGooseControlBlock_getFixedOffs (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern PhyComAddress ClientGooseControlBlock_getDstAddress(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern PhyComAddress ClientGooseControlBlock_getDstAddress (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientGooseControlBlock_getDstAddress_addr(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientGooseControlBlock_getDstAddress_addr(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern byte ClientGooseControlBlock_getDstAddress_priority(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern byte ClientGooseControlBlock_getDstAddress_priority(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt16 ClientGooseControlBlock_getDstAddress_vid(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt16 ClientGooseControlBlock_getDstAddress_vid(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt16 ClientGooseControlBlock_getDstAddress_appid(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt16 ClientGooseControlBlock_getDstAddress_appid(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientGooseControlBlock_setDstAddress(IntPtr self, PhyComAddress value); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientGooseControlBlock_setDstAddress (IntPtr self, PhyComAddress value); - - private IntPtr self; - private IntPtr connection; - private string objectReference; + private IntPtr self; + private IntPtr connection; + private string objectReference; - private bool isDisposed = false; + private bool isDisposed = false; - private bool flagGoEna = false; - private bool flagGoID = false; - private bool flagDatSet = false; - private bool flagDstAddress = false; + private bool flagGoEna = false; + private bool flagGoID = false; + private bool flagDatSet = false; + private bool flagDstAddress = false; - internal GooseControlBlock(string objectReference, IntPtr connection) - { - self = ClientGooseControlBlock_create (objectReference); - this.connection = connection; - this.objectReference = objectReference; - } + internal GooseControlBlock(string objectReference, IntPtr connection) + { + self = ClientGooseControlBlock_create(objectReference); + this.connection = connection; + this.objectReference = objectReference; + } - public string GetObjectReference () - { - return this.objectReference; - } + public string GetObjectReference() + { + return objectReference; + } - /// - /// Read all GoCB values from the server - /// - /// This exception is thrown if there is a connection or service error - public void GetCBValues () - { - int error; + /// + /// Read all GoCB values from the server + /// + /// This exception is thrown if there is a connection or service error + 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); - } + if (error != 0) + throw new IedConnectionException("getGoCBValues service failed", error); + } - private void - resetSendFlags() - { - flagGoEna = false; - flagGoID = false; - flagDatSet = false; - flagDstAddress = false; - } + private void + resetSendFlags() + { + flagGoEna = false; + flagGoID = false; + flagDatSet = false; + flagDstAddress = false; + } - public void SetCBValues (bool singleRequest) - { - UInt32 parametersMask = 0; + public void SetCBValues(bool singleRequest) + { + UInt32 parametersMask = 0; - if (flagGoEna) - parametersMask += 1; + if (flagGoEna) + parametersMask += 1; - if (flagGoID) - parametersMask += 2; + if (flagGoID) + parametersMask += 2; - if (flagDatSet) - parametersMask += 4; + if (flagDatSet) + parametersMask += 4; - if (flagDstAddress) - parametersMask += 32; + if (flagDstAddress) + parametersMask += 32; - int error; + 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); - } + if (error != 0) + throw new IedConnectionException("setGoCBValues service failed", error); + } - public void SetCBValues () - { - SetCBValues (true); - } + public void SetCBValues() + { + SetCBValues(true); + } - public bool GetGoEna() - { - return ClientGooseControlBlock_getGoEna (self); - } + public bool GetGoEna() + { + return ClientGooseControlBlock_getGoEna(self); + } - public void SetGoEna(bool value) - { - ClientGooseControlBlock_setGoEna (self, value); + public void SetGoEna(bool value) + { + ClientGooseControlBlock_setGoEna(self, value); - flagGoEna = true; - } + flagGoEna = true; + } - public string GetGoID() - { - IntPtr goIdRef = ClientGooseControlBlock_getGoID (self); + public string GetGoID() + { + IntPtr goIdRef = ClientGooseControlBlock_getGoID(self); - return Marshal.PtrToStringAnsi (goIdRef); - } + return Marshal.PtrToStringAnsi(goIdRef); + } - public void SetGoID (string goID) - { - ClientGooseControlBlock_setGoID (self, goID); + public void SetGoID(string goID) + { + ClientGooseControlBlock_setGoID(self, goID); - flagGoID = true; - } + flagGoID = true; + } - public string GetDatSet() - { - IntPtr datSetRef = ClientGooseControlBlock_getDatSet (self); + public string GetDatSet() + { + IntPtr datSetRef = ClientGooseControlBlock_getDatSet(self); - return Marshal.PtrToStringAnsi (datSetRef); - } + return Marshal.PtrToStringAnsi(datSetRef); + } - public void SetDataSet(string datSet) - { - ClientGooseControlBlock_setDatSet (self, datSet); + public void SetDataSet(string datSet) + { + ClientGooseControlBlock_setDatSet(self, datSet); - flagDatSet = true; - } + flagDatSet = true; + } - public UInt32 GetConfRev() - { - return ClientGooseControlBlock_getConfRev (self); - } + public UInt32 GetConfRev() + { + return ClientGooseControlBlock_getConfRev(self); + } - public bool GetNdsComm() - { - return ClientGooseControlBlock_getNdsComm (self); - } + public bool GetNdsComm() + { + return ClientGooseControlBlock_getNdsComm(self); + } - public UInt32 GetMinTime() - { - return ClientGooseControlBlock_getMinTime (self); - } + public UInt32 GetMinTime() + { + return ClientGooseControlBlock_getMinTime(self); + } - public UInt32 GetMaxTime() - { - return ClientGooseControlBlock_getMaxTime (self); - } + public UInt32 GetMaxTime() + { + return ClientGooseControlBlock_getMaxTime(self); + } - public bool GetFixedOffs() - { - return ClientGooseControlBlock_getFixedOffs (self); - } + public bool GetFixedOffs() + { + return ClientGooseControlBlock_getFixedOffs(self); + } - public PhyComAddress GetDstAddress() - { - PhyComAddress addr = new PhyComAddress(); + public PhyComAddress GetDstAddress() + { + PhyComAddress addr = new PhyComAddress(); - IntPtr value = ClientGooseControlBlock_getDstAddress_addr(self); + IntPtr value = ClientGooseControlBlock_getDstAddress_addr(self); - MmsValue mmsValue = new MmsValue(value); + MmsValue mmsValue = new MmsValue(value); - byte[] dstMacAddr = mmsValue.getOctetString(); + byte[] dstMacAddr = mmsValue.getOctetString(); - dstMacAddr.CopyTo(addr.dstAddress, 0); + dstMacAddr.CopyTo(addr.dstAddress, 0); - addr.dstAddress = dstMacAddr; + addr.dstAddress = dstMacAddr; - addr.appId = ClientGooseControlBlock_getDstAddress_appid(self); - addr.vlanId = ClientGooseControlBlock_getDstAddress_vid(self); - addr.vlanPriority = ClientGooseControlBlock_getDstAddress_priority(self); + addr.appId = ClientGooseControlBlock_getDstAddress_appid(self); + addr.vlanId = ClientGooseControlBlock_getDstAddress_vid(self); + addr.vlanPriority = ClientGooseControlBlock_getDstAddress_priority(self); - return addr; - } + return addr; + } - public void SetDstAddress(PhyComAddress value) - { - ClientGooseControlBlock_setDstAddress (self, value); + public void SetDstAddress(PhyComAddress value) + { + ClientGooseControlBlock_setDstAddress(self, value); - flagDstAddress = true; - } + flagDstAddress = true; + } - public void Dispose() - { - if (isDisposed == false) { - isDisposed = true; - ClientGooseControlBlock_destroy (self); - self = IntPtr.Zero; - } - } + public void Dispose() + { + if (isDisposed == false) + { + isDisposed = true; + ClientGooseControlBlock_destroy(self); + self = IntPtr.Zero; + } + } - ~GooseControlBlock() - { - Dispose (); - } + ~GooseControlBlock() + { + Dispose(); + } - } - } + } + } } \ No newline at end of file diff --git a/dotnet/IEC61850forCSharp/GooseSubscriber.cs b/dotnet/IEC61850forCSharp/GooseSubscriber.cs index 29b64c01..acd6ddaf 100644 --- a/dotnet/IEC61850forCSharp/GooseSubscriber.cs +++ b/dotnet/IEC61850forCSharp/GooseSubscriber.cs @@ -1,7 +1,7 @@ /* * GooseSubscriber.cs * - * Copyright 2017 Michael Zillgith + * Copyright 2017-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -21,345 +21,351 @@ * 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 { - namespace GOOSE - { - - namespace Subscriber - { - - /// - /// GOOSE listener. - /// - public delegate void GooseListener (GooseSubscriber report, object parameter); - - public class GooseReceiver : IDisposable - { - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr GooseReceiver_create (); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void GooseReceiver_addSubscriber(IntPtr self, IntPtr subscriber); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void GooseReceiver_removeSubscriber(IntPtr self, IntPtr subscriber); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void GooseReceiver_start(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void GooseReceiver_stop(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool GooseReceiver_isRunning (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void GooseReceiver_destroy(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void GooseReceiver_setInterfaceId(IntPtr self, string interfaceId); - - private IntPtr self; - - private bool isDisposed = false; - - private List subscribers = new List(); - - public GooseReceiver() - { - self = GooseReceiver_create (); - } - - public void SetInterfaceId(string interfaceId) - { - GooseReceiver_setInterfaceId (self, interfaceId); - } - - /// - /// Add the subscriber to be handled by this receiver instance - /// - /// A GooseSubscriber can only be added to one GooseReceiver! - /// - public void AddSubscriber(GooseSubscriber subscriber) - { - if (subscriber.attachedToReceiver == false) - { - subscriber.attachedToReceiver = true; - GooseReceiver_addSubscriber(self, subscriber.self); - subscribers.Add(subscriber); - } - } - - public void RemoveSubscriber(GooseSubscriber subscriber) - { - if (subscriber.attachedToReceiver) - { - GooseReceiver_removeSubscriber(self, subscriber.self); - subscribers.Remove(subscriber); - subscriber.attachedToReceiver = false; - } - } - - public void Start() - { - GooseReceiver_start (self); - } - - public void Stop() - { - GooseReceiver_stop (self); - } - - public bool IsRunning() - { - return GooseReceiver_isRunning (self); - } + namespace GOOSE + { + + namespace Subscriber + { + + /// + /// GOOSE listener. + /// + public delegate void GooseListener(GooseSubscriber report, object parameter); + + public class GooseReceiver : IDisposable + { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr GooseReceiver_create(); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void GooseReceiver_addSubscriber(IntPtr self, IntPtr subscriber); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void GooseReceiver_removeSubscriber(IntPtr self, IntPtr subscriber); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void GooseReceiver_start(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void GooseReceiver_stop(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool GooseReceiver_isRunning(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void GooseReceiver_destroy(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void GooseReceiver_setInterfaceId(IntPtr self, string interfaceId); + + private IntPtr self; + + private bool isDisposed = false; + + private List subscribers = new List(); + + public GooseReceiver() + { + self = GooseReceiver_create(); + } + + public void SetInterfaceId(string interfaceId) + { + GooseReceiver_setInterfaceId(self, interfaceId); + } + + /// + /// Add the subscriber to be handled by this receiver instance + /// + /// A GooseSubscriber can only be added to one GooseReceiver! + /// + public void AddSubscriber(GooseSubscriber subscriber) + { + if (subscriber.attachedToReceiver == false) + { + subscriber.attachedToReceiver = true; + GooseReceiver_addSubscriber(self, subscriber.self); + subscribers.Add(subscriber); + } + } + + public void RemoveSubscriber(GooseSubscriber subscriber) + { + if (subscriber.attachedToReceiver) + { + GooseReceiver_removeSubscriber(self, subscriber.self); + subscribers.Remove(subscriber); + subscriber.attachedToReceiver = false; + } + } + + public void Start() + { + GooseReceiver_start(self); + } + + public void Stop() + { + GooseReceiver_stop(self); + } + + public bool IsRunning() + { + return GooseReceiver_isRunning(self); + } + + public void Dispose() + { + if (isDisposed == false) + { + isDisposed = true; + GooseReceiver_destroy(self); + self = IntPtr.Zero; + } + } + + ~GooseReceiver() + { + Dispose(); + } + } + + + /// + /// Representing a GOOSE subscriber + /// + /// + /// NOTE: After SetListener is called, do not call any function outside of + /// the callback handler! + /// + public class GooseSubscriber : IDisposable + { + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate void InternalGooseListener(IntPtr subscriber, IntPtr parameter); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt32 GooseSubscriber_getStNum(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt32 GooseSubscriber_getTimeAllowedToLive(IntPtr self); - public void Dispose() - { - if (isDisposed == false) { - isDisposed = true; - GooseReceiver_destroy (self); - self = IntPtr.Zero; - } - } - - ~GooseReceiver() - { - Dispose (); - } - } - - - /// - /// Representing a GOOSE subscriber - /// - /// - /// NOTE: After SetListener is called, do not call any function outside of - /// the callback handler! - /// - public class GooseSubscriber : IDisposable - { - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void InternalGooseListener (IntPtr subscriber, IntPtr parameter); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt32 GooseSubscriber_getStNum (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt32 GooseSubscriber_getTimeAllowedToLive (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt64 GooseSubscriber_getTimestamp (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr GooseSubscriber_getDataSetValues(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr GooseSubscriber_getGoId(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr GooseSubscriber_getGoCbRef(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr GooseSubscriber_getDataSet(IntPtr self); - - internal IntPtr self; - - private bool isDisposed = false; - - // don't call native destructor when attached to a receiver - internal bool attachedToReceiver = false; - - private GooseListener listener = null; - private object listenerParameter = null; - - private event InternalGooseListener internalListener = null; - - private void internalGooseListener (IntPtr subscriber, IntPtr parameter) - { - try { - - if (listener != null) { - listener(this, listenerParameter); - } - - } catch (Exception e) - { - // older versions of mono 2.10 (for linux?) cause this exception - Console.WriteLine(e.Message); - } - } - - public GooseSubscriber(string goCbRef) - { - self = GooseSubscriber_create (goCbRef, IntPtr.Zero); - } - - public void SetAppId(UInt16 appId) - { - GooseSubscriber_setAppId (self, appId); - } - - public bool IsValid () - { - return GooseSubscriber_isValid (self); - } - - public void SetListener(GooseListener listener, object parameter) - { - this.listener = listener; - this.listenerParameter = parameter; - - if (internalListener == null) { - internalListener = new InternalGooseListener (internalGooseListener); - - GooseSubscriber_setListener (self, internalListener, IntPtr.Zero); - } - } - - public string GetGoId() - { - return Marshal.PtrToStringAnsi(GooseSubscriber_getGoId(self)); - } - - public string GetGoCbRef() - { - return Marshal.PtrToStringAnsi(GooseSubscriber_getGoCbRef(self)); - } - - public string GetDataSet() - { - return Marshal.PtrToStringAnsi(GooseSubscriber_getDataSet(self)); - } - - public UInt32 GetStNum() - { - return GooseSubscriber_getStNum (self); - } - - public UInt32 GetSqNum() - { - return GooseSubscriber_getSqNum (self); - } - - public bool IsTest() - { - return GooseSubscriber_isTest (self); - } - - public UInt32 GetConfRev() - { - return GooseSubscriber_getConfRev (self); - } - - public bool NeedsCommission() - { - return GooseSubscriber_needsCommission (self); - } - - public UInt32 GetTimeAllowedToLive() - { - return GooseSubscriber_getTimeAllowedToLive (self); - } - - public UInt64 GetTimestamp () - { - return GooseSubscriber_getTimestamp (self); - } - - public DateTimeOffset GetTimestampsDateTimeOffset () - { - UInt64 entryTime = GetTimestamp (); - - DateTimeOffset retVal = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero); - - return retVal.AddMilliseconds (entryTime); - } - - /// - /// Get the values of the GOOSE data set from the last received GOOSE message - /// - /// - /// The MmsValue instance is only valid in the context of the GooseLister callback. - /// Do not store for outside use! - /// - /// The data set values. - public MmsValue GetDataSetValues() - { - IntPtr mmsValueRef = GooseSubscriber_getDataSetValues (self); - - return (new MmsValue (mmsValueRef)); - } - - /// - /// Releases all resource used by the object. - /// - /// > - /// This function has only to be called when the - /// has not been added to the GooseReceiver or has been removed from the GooseReceiver. - /// When the GooseReceiver holds a reference it will take care for releasing the resources. - /// In this case Dispose MUST not be called! Otherwise the natice resources will be - /// released twice. - /// - public void Dispose() - { - if (isDisposed == false) { - isDisposed = true; - - if (attachedToReceiver == false) - GooseSubscriber_destroy (self); - - self = IntPtr.Zero; - } - } - - ~GooseSubscriber() - { - Dispose(); - } + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt64 GooseSubscriber_getTimestamp(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr GooseSubscriber_getDataSetValues(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr GooseSubscriber_getGoId(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr GooseSubscriber_getGoCbRef(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr GooseSubscriber_getDataSet(IntPtr self); + + internal IntPtr self; + + private bool isDisposed = false; + + // don't call native destructor when attached to a receiver + internal bool attachedToReceiver = false; + + private GooseListener listener = null; + private object listenerParameter = null; + + private event InternalGooseListener internalListener = null; + + private void internalGooseListener(IntPtr subscriber, IntPtr parameter) + { + try + { + + if (listener != null) + { + listener(this, listenerParameter); + } + + } + catch (Exception e) + { + // older versions of mono 2.10 (for linux?) cause this exception + Console.WriteLine(e.Message); + } + } + + public GooseSubscriber(string goCbRef) + { + self = GooseSubscriber_create(goCbRef, IntPtr.Zero); + } + + public void SetAppId(UInt16 appId) + { + GooseSubscriber_setAppId(self, appId); + } + + public bool IsValid() + { + return GooseSubscriber_isValid(self); + } + + public void SetListener(GooseListener listener, object parameter) + { + this.listener = listener; + listenerParameter = parameter; + + if (internalListener == null) + { + internalListener = new InternalGooseListener(internalGooseListener); + + GooseSubscriber_setListener(self, internalListener, IntPtr.Zero); + } + } + + public string GetGoId() + { + return Marshal.PtrToStringAnsi(GooseSubscriber_getGoId(self)); + } + + public string GetGoCbRef() + { + return Marshal.PtrToStringAnsi(GooseSubscriber_getGoCbRef(self)); + } + + public string GetDataSet() + { + return Marshal.PtrToStringAnsi(GooseSubscriber_getDataSet(self)); + } + + public UInt32 GetStNum() + { + return GooseSubscriber_getStNum(self); + } + + public UInt32 GetSqNum() + { + return GooseSubscriber_getSqNum(self); + } + + public bool IsTest() + { + return GooseSubscriber_isTest(self); + } + + public UInt32 GetConfRev() + { + return GooseSubscriber_getConfRev(self); + } + + public bool NeedsCommission() + { + return GooseSubscriber_needsCommission(self); + } + + public UInt32 GetTimeAllowedToLive() + { + return GooseSubscriber_getTimeAllowedToLive(self); + } + + public UInt64 GetTimestamp() + { + return GooseSubscriber_getTimestamp(self); + } + + public DateTimeOffset GetTimestampsDateTimeOffset() + { + UInt64 entryTime = GetTimestamp(); + + DateTimeOffset retVal = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); + + return retVal.AddMilliseconds(entryTime); + } + + /// + /// Get the values of the GOOSE data set from the last received GOOSE message + /// + /// + /// The MmsValue instance is only valid in the context of the GooseLister callback. + /// Do not store for outside use! + /// + /// The data set values. + public MmsValue GetDataSetValues() + { + IntPtr mmsValueRef = GooseSubscriber_getDataSetValues(self); + + return (new MmsValue(mmsValueRef)); + } + + /// + /// Releases all resource used by the object. + /// + /// > + /// This function has only to be called when the + /// has not been added to the GooseReceiver or has been removed from the GooseReceiver. + /// When the GooseReceiver holds a reference it will take care for releasing the resources. + /// In this case Dispose MUST not be called! Otherwise the natice resources will be + /// released twice. + /// + public void Dispose() + { + if (isDisposed == false) + { + isDisposed = true; + + if (attachedToReceiver == false) + GooseSubscriber_destroy(self); + + self = IntPtr.Zero; + } + } + + ~GooseSubscriber() + { + Dispose(); + } } - } - - } + } + + } } \ No newline at end of file diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs index 4530c9ed..d6af494d 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs @@ -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,11 +103,11 @@ namespace IEC61850 self = mmsConnection; } - ~MmsConnection () + ~MmsConnection() { if (selfDestroy) - if (self != IntPtr.Zero) - MmsConnection_destroy(self); + if (self != IntPtr.Zero) + MmsConnection_destroy(self); } private void FreeHGlobaleDeleteFunction(IntPtr pointer) @@ -140,7 +137,7 @@ namespace IEC61850 throw new IedConnectionException("Failed to read server identity"); MmsServerIdentity serverIdentity = (MmsServerIdentity) - Marshal.PtrToStructure(identity, typeof(MmsServerIdentity)); + Marshal.PtrToStructure(identity, typeof(MmsServerIdentity)); MmsServerIdentity_destroy(identity); @@ -194,7 +191,7 @@ namespace IEC61850 int error; IntPtr mmsValue = MmsConnection_readMultipleVariables(self, out error, domainName, linkedList); - + LinkedList_destroyDeep(linkedList, new LinkedListValueDeleteFunction(FreeHGlobaleDeleteFunction)); if (error != 0) @@ -343,7 +340,7 @@ namespace IEC61850 } } - ~MmsJournalEntry () + ~MmsJournalEntry() { Dispose(); } @@ -356,7 +353,7 @@ namespace IEC61850 /// user provided callback parameter /// Error code of response or timeout error in case of a response timeout /// the report control block instance - public delegate void GetRCBValuesHandler(UInt32 invokeId,object parameter,IedClientError err,ReportControlBlock rcb); + public delegate void GetRCBValuesHandler(UInt32 invokeId, object parameter, IedClientError err, ReportControlBlock rcb); /// /// Asynchonous service handler for the set RCB values service @@ -365,7 +362,7 @@ namespace IEC61850 /// user provided callback parameter /// Error code of response or timeout error in case of a response timeout /// the report control block instance - public delegate void SetRCBValuesHandler(UInt32 invokeId,object parameter,IedClientError err,ReportControlBlock rcb); + public delegate void SetRCBValuesHandler(UInt32 invokeId, object parameter, IedClientError err, ReportControlBlock rcb); /// /// Generic asynchonous service handler - used by simple services that have only success or error result @@ -373,7 +370,7 @@ namespace IEC61850 /// The invoke ID of the request triggering this callback /// user provided callback parameter /// Error code of response or timeout error in case of a response timeout - public delegate void GenericServiceHandler(UInt32 invokeId,object parameter,IedClientError err); + public delegate void GenericServiceHandler(UInt32 invokeId, object parameter, IedClientError err); /// /// 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); /// /// 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); /// /// Called when there is a change in the connection state @@ -582,56 +579,56 @@ 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)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_readObjectAsync(IntPtr self, out int error, string objRef, int fc, 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)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_writeObjectAsync(IntPtr self, out int error, string objRef, int fc, 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)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_getServerDirectoryAsync(IntPtr self, out int error, string continueAfter, IntPtr result, IedConnection_GetNameListHandler handler, IntPtr parameter); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_getLogicalDeviceVariablesAsync(IntPtr self, out int error, string ldName, string continueAfter, IntPtr result, IedConnection_GetNameListHandler handler, IntPtr parameter); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_getLogicalDeviceDataSetsAsync(IntPtr self, out int error, string ldName, string continueAfter, IntPtr result, 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)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_queryLogByTimeAsync(IntPtr self, out int error, string logReference, UInt64 startTime, UInt64 endTime, IedConnection_QueryLogHandler handler, IntPtr parameter); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_queryLogAfterAsync(IntPtr self, out int error, string logReference, IntPtr entryID, UInt64 timeStamp, IedConnection_QueryLogHandler handler, IntPtr parameter); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void IedConnection_GetVariableSpecificationHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr spec); + private delegate void IedConnection_GetVariableSpecificationHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr spec); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_getVariableSpecificationAsync(IntPtr self, out int error, string dataAttributeReference, int fc, IedConnection_GetVariableSpecificationHandler handler, IntPtr parameter); @@ -639,7 +636,7 @@ namespace IEC61850 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void IedConnection_ReadDataSetHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr dataSet); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_readDataSetValuesAsync(IntPtr self, out int error, string dataSetReference, IntPtr dataSet, IedConnection_ReadDataSetHandler handler, IntPtr parameter); @@ -663,26 +660,26 @@ 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)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_getRCBValuesAsync(IntPtr self, out int error, string rcbReference, IntPtr updateRcb, 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)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_setRCBValuesAsync(IntPtr self, out int error, IntPtr rcb, UInt32 parametersMask, [MarshalAs(UnmanagedType.I1)] bool singleRequest, IedConnection_GenericServiceHandler handler, IntPtr parameter); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 - IedConnection_deleteFileAsync(IntPtr self, out int error, string fileName, + IedConnection_deleteFileAsync(IntPtr self, out int error, string fileName, IedConnection_GenericServiceHandler handler, IntPtr parameter); - + /******************** * FileDirectoryEntry @@ -706,7 +703,7 @@ namespace IEC61850 static extern void LinkedList_destroyStatic(IntPtr self); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void LinkedListValueDeleteFunction(IntPtr pointer); + private delegate void LinkedListValueDeleteFunction(IntPtr pointer); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void LinkedList_destroyDeep(IntPtr list, LinkedListValueDeleteFunction valueDeleteFunction); @@ -759,7 +756,7 @@ namespace IEC61850 } } - ~IedConnection () + ~IedConnection() { Dispose(); } @@ -897,7 +894,7 @@ namespace IEC61850 if (error != 0) throw new IedConnectionException("Connect to " + hostname + ":" + tcpPort + " failed", error); - + } /// @@ -1303,7 +1300,7 @@ namespace IEC61850 { int error; - IntPtr mmsValue = IedConnection_readObject(connection, out error, objectReference, (int)fc); + IntPtr mmsValue = IedConnection_readObject(connection, out error, objectReference, (int)fc); if (error != 0) throw new IedConnectionException("Reading value failed", error); @@ -1530,7 +1527,7 @@ namespace IEC61850 handle.Free(); IedClientError clientError = (IedClientError)err; - + handler(invokeId, handlerParameter, clientError); } @@ -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) { @@ -1649,16 +1646,16 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_getFile(IntPtr self, out int error, string fileName, InternalIedClientGetFileHandler handler, - IntPtr handlerParameter); + IntPtr handlerParameter); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void IedConnection_setFile(IntPtr self, out int error, string sourceFilename, string destinationFilename); - + static extern void IedConnection_setFile(IntPtr self, out int error, string sourceFilename, string destinationFilename); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] 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 { @@ -1693,7 +1690,7 @@ namespace IEC61850 GCHandle handle = GCHandle.Alloc(getFileCallback); - IedConnection_getFile(connection, out error, fileName, new InternalIedClientGetFileHandler(iedClientGetFileHandler), + IedConnection_getFile(connection, out error, fileName, new InternalIedClientGetFileHandler(iedClientGetFileHandler), GCHandle.ToIntPtr(handle)); if (error != 0) @@ -1720,7 +1717,7 @@ namespace IEC61850 { int error; - IedConnection_setFile(connection, out error, sourceFilename, destinationFilename); + IedConnection_setFile(connection, out error, sourceFilename, destinationFilename); if (error != 0) throw new IedConnectionException("Error uploading file", error); @@ -1743,7 +1740,7 @@ namespace IEC61850 /// true, continue the file download when moreFollows is true, false, stop file download public delegate bool GetFileAsyncHandler(UInt32 invokeId, object parameter, IedClientError err, UInt32 originalInvokeId, byte[] buffer, bool moreFollows); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 IedConnection_getFileAsync(IntPtr self, out int error, string fileName, IedConnection_GetFileAsyncHandler handler, IntPtr parameter); @@ -1763,15 +1760,15 @@ namespace IEC61850 IedClientError clientError = (IedClientError)err; byte[] bytes = null; - + if (clientError == IedClientError.IED_ERROR_OK) { bytes = new byte[bytesRead]; Marshal.Copy(buffer, bytes, 0, (int)bytesRead); - } - - bool retVal = handler(invokeId, handlerParameter, clientError, originalInvokeId, bytes, moreFollows); + } + + bool retVal = handler(invokeId, handlerParameter, clientError, originalInvokeId, bytes, moreFollows); if (clientError != IedClientError.IED_ERROR_OK) { @@ -1929,7 +1926,7 @@ namespace IEC61850 IedConnection_installConnectionClosedHandler(connection, connectionClosedHandler, connection); } - userProvidedConnectionClosedHandler = handler; + userProvidedConnectionClosedHandler = handler; } private void MyStateChangedHandler(IntPtr parameter, IntPtr IedConnection, int newState) @@ -2011,11 +2008,11 @@ namespace IEC61850 if (dataSet != null) nativeClientDataSet = dataSet.getNativeInstance(); - + int error; nativeClientDataSet = IedConnection_readDataSetValues(connection, out error, dataSetReference, nativeClientDataSet); - + if (error != 0) throw new IedConnectionException("Reading data set failed", error); @@ -2338,7 +2335,7 @@ namespace IEC61850 /// user provided callback parameter /// Error code of response or timeout error in case of a response timeout /// The read result value or null in case of an error - 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); /// Read the variable specification (type description of a DA or FCDO /// The object reference of a DA or FCDO. @@ -2437,7 +2434,7 @@ namespace IEC61850 if (internalGetVariableSpecificationHandler == null) internalGetVariableSpecificationHandler = new IedConnection_GetVariableSpecificationHandler(nativeGetVariableSpecifcationHandler); - UInt32 invokeId = IedConnection_getVariableSpecificationAsync(connection, out error, objectReference, (int)fc, internalGetVariableSpecificationHandler, GCHandle.ToIntPtr(handle)); + UInt32 invokeId = IedConnection_getVariableSpecificationAsync(connection, out error, objectReference, (int)fc, internalGetVariableSpecificationHandler, GCHandle.ToIntPtr(handle)); if (error != 0) { @@ -2469,11 +2466,11 @@ namespace IEC61850 if (dataSet == null) dataSet = new DataSet(nativeDataSet); } - + 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); /// /// Read the values of a data set (GetDataSetValues service) - asynchronous version @@ -2504,7 +2501,7 @@ namespace IEC61850 if (internalReadDataSetHandler == null) internalReadDataSetHandler = new IedConnection_ReadDataSetHandler(nativeReadDataSetHandler); - UInt32 invokeId = IedConnection_readDataSetValuesAsync(connection, out error, dataSetReference, dataSetPtr, internalReadDataSetHandler, GCHandle.ToIntPtr(handle)); + UInt32 invokeId = IedConnection_readDataSetValuesAsync(connection, out error, dataSetReference, dataSetPtr, internalReadDataSetHandler, GCHandle.ToIntPtr(handle)); if (error != 0) { @@ -2521,7 +2518,7 @@ namespace IEC61850 /// The invoke ID of the reqeust triggering this callback /// user provided callback parameter /// Error code of response or timeout error in case of a response timeout - 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,11 +2560,11 @@ namespace IEC61850 return invokeId; } - public delegate void GetNameListHandler(UInt32 invokeId,object parameter,IedClientError err,List nameList,bool moreFollows); + public delegate void GetNameListHandler(UInt32 invokeId, object parameter, IedClientError err, List nameList, bool moreFollows); private IedConnection_GetNameListHandler internalGetNameListHandler = null; - private void nativeGetNameListHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr nameList, [MarshalAs(UnmanagedType.I1)] bool moreFollows) + private void nativeGetNameListHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr nameList, [MarshalAs(UnmanagedType.I1)] bool moreFollows) { GCHandle handle = GCHandle.FromIntPtr(parameter); @@ -2692,11 +2689,11 @@ namespace IEC61850 return invokeId; } - public delegate void QueryLogHandler(UInt32 invokeId,object parameter,IedClientError err,List journalEntries,bool moreFollows); + public delegate void QueryLogHandler(UInt32 invokeId, object parameter, IedClientError err, List journalEntries, bool moreFollows); private IedConnection_QueryLogHandler internalQueryLogHandler = null; - private void nativeQueryLogHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr journalEntries, + private void nativeQueryLogHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr journalEntries, [MarshalAs(UnmanagedType.I1)] bool moreFollows) { GCHandle handle = GCHandle.FromIntPtr(parameter); @@ -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; } } diff --git a/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs b/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs index 980d9ceb..7f1c69fd 100644 --- a/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs @@ -1,7 +1,7 @@ /* * IEC61850CommonAPI.cs * - * Copyright 2014-2024 Michael Zillgith + * Copyright 2014-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -26,405 +26,422 @@ using System.Runtime.InteropServices; namespace IEC61850 { - namespace Common - { - - public enum Iec61850Edition : byte - { - EDITION_1 = 0, - EDITION_2 = 1, - EDITION_2_1 = 2 - } - - public class LibIEC61850 - { - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr LibIEC61850_getVersionString(); - - /// - /// Get the version string of the native libiec61850 library - /// - /// The version string in format MAJOR.MINOR.PATCH - public static string GetVersionString() - { - return Marshal.PtrToStringAnsi (LibIEC61850_getVersionString ()); - } - - /// - /// Converts millisecond timestamp to a DateTime object - /// - /// The DateTime object representing the value of the timestamp - /// The timestamp in milliseconds since epoch (UTC) - public static DateTime MsTimestampToDateTime(ulong msTime) - { - DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - - ulong seconds = msTime / 1000; - ulong millies = msTime % 1000; - - dateTime.AddSeconds ((double) seconds); - dateTime.AddMilliseconds((double) millies); - - return dateTime; - } - - /// - /// Converts a DateTime object in milliseconds since epoch timestamp (UTC) - /// - /// The timestamp in ms - /// The DateTime object to convert - public static ulong DateTimeToMsTimestamp(DateTime dateTime) - { - return (ulong) (dateTime.ToUniversalTime ().Subtract (new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds); - } - } - - [StructLayout(LayoutKind.Sequential)] - public class PhyComAddress - { - public byte vlanPriority; - public UInt16 vlanId; - public UInt16 appId; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst=6)] + namespace Common + { + + public enum Iec61850Edition : byte + { + EDITION_1 = 0, + EDITION_2 = 1, + EDITION_2_1 = 2 + } + + public class LibIEC61850 + { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr LibIEC61850_getVersionString(); + + /// + /// Get the version string of the native libiec61850 library + /// + /// The version string in format MAJOR.MINOR.PATCH + public static string GetVersionString() + { + return Marshal.PtrToStringAnsi(LibIEC61850_getVersionString()); + } + + /// + /// Converts millisecond timestamp to a DateTime object + /// + /// The DateTime object representing the value of the timestamp + /// The timestamp in milliseconds since epoch (UTC) + public static DateTime MsTimestampToDateTime(ulong msTime) + { + DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + + ulong seconds = msTime / 1000; + ulong millies = msTime % 1000; + + dateTime.AddSeconds(seconds); + dateTime.AddMilliseconds(millies); + + return dateTime; + } + + /// + /// Converts a DateTime object in milliseconds since epoch timestamp (UTC) + /// + /// The timestamp in ms + /// The DateTime object to convert + public static ulong DateTimeToMsTimestamp(DateTime dateTime) + { + return (ulong)(dateTime.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class PhyComAddress + { + public byte vlanPriority; + public UInt16 vlanId; + public UInt16 appId; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public byte[] dstAddress = new byte[6]; } - /// - /// MMS data access error for MmsValue type MMS_DATA_ACCESS_ERROR - /// - public enum MmsDataAccessError { - NO_RESPONSE = -2, /* for server internal purposes only! */ - SUCCESS = -1, - OBJECT_INVALIDATED = 0, - HARDWARE_FAULT = 1, - TEMPORARILY_UNAVAILABLE = 2, - OBJECT_ACCESS_DENIED = 3, - OBJECT_UNDEFINED = 4, - INVALID_ADDRESS = 5, - TYPE_UNSUPPORTED = 6, - TYPE_INCONSISTENT = 7, - OBJECT_ATTRIBUTE_INCONSISTENT = 8, - OBJECT_ACCESS_UNSUPPORTED = 9, - OBJECT_NONE_EXISTENT = 10, - OBJECT_VALUE_INVALID = 11, - UNKNOWN = 12, - } - - [Flags] - public enum TriggerOptions { - NONE = 0, - /** send report when value of data changed */ - DATA_CHANGED = 1, - /** send report when quality of data changed */ - QUALITY_CHANGED = 2, - /** send report when data or quality is updated */ - DATA_UPDATE = 4, - /** periodic transmission of all data set values */ - INTEGRITY = 8, - /** general interrogation (on client request) */ - GI = 16, - /** Report will be triggered only on rising edge (transient variable) */ - TRG_OPT_TRANSIENT = 128 - } - - /// - /// SmpMod values - /// - public enum SmpMod { - SAMPLES_PER_PERIOD = 0, - SAMPLES_PER_SECOND = 1, - SECONDS_PER_SAMPLE = 2 - } - - /// - /// Values for Sampled Values (SV) OptFlds - /// - [Flags] - public enum SVOptions { - NONE = 0, - REFRESH_TIME = 1, - SAMPLE_SYNC = 2, - SAMPLE_RATE = 4, - DATA_SET = 8, - SECURITY = 16, - ALL = 31 - } - - [Flags] - public enum ReportOptions { - NONE = 0, - SEQ_NUM = 1, - TIME_STAMP = 2, - REASON_FOR_INCLUSION = 4, - DATA_SET = 8, - DATA_REFERENCE = 16, - BUFFER_OVERFLOW = 32, - ENTRY_ID = 64, - CONF_REV = 128, - SEGMENTATION = 256, - ALL = SEQ_NUM | TIME_STAMP | REASON_FOR_INCLUSION | DATA_SET | DATA_REFERENCE | - BUFFER_OVERFLOW | ENTRY_ID | CONF_REV | SEGMENTATION - } - - public enum Validity - { - GOOD = 0, - RESERVED = 1, - INVALID = 2, - QUESTIONABLE = 3 - } - - /// - /// The quality of a data object. - /// - public class Quality - { - private UInt16 value; - - private const UInt16 QUALITY_DETAIL_OVERFLOW = 4; - private const UInt16 QUALITY_DETAIL_OUT_OF_RANGE = 8; - private const UInt16 QUALITY_DETAIL_BAD_REFERENCE = 16; - private const UInt16 QUALITY_DETAIL_OSCILLATORY = 32; - private const UInt16 QUALITY_DETAIL_FAILURE = 64; - private const UInt16 QUALITY_DETAIL_OLD_DATA = 128; - private const UInt16 QUALITY_DETAIL_INCONSISTENT = 256; - private const UInt16 QUALITY_DETAIL_INACCURATE = 512; - private const UInt16 QUALITY_SOURCE_SUBSTITUTED = 1024; - private const UInt16 QUALITY_TEST = 2048; - private const UInt16 QUALITY_OPERATOR_BLOCKED = 4096; - private const UInt16 QUALITY_DERIVED = 8192; - - public ushort Value => value; - - public override string ToString () - { - return GetValidity ().ToString (); - - } - - public Quality (int bitStringValue) - { - value = (UInt16)bitStringValue; - } - - public Quality () - { - value = 0; - } - - public Validity GetValidity () - { - int qualityVal = value & 0x3; - - return (Validity)qualityVal; - } - - public void SetValidity (Validity validity) - { - value = (UInt16)(value & 0xfffc); - - value += (ushort)validity; - } - - public Validity Validity - { - get {return GetValidity ();} - set { SetValidity (value); } - } - - public bool Overflow - { - get { return ((this.value & QUALITY_DETAIL_OVERFLOW) != 0);} - set { - if (value) - this.value |= QUALITY_DETAIL_OVERFLOW; - else - this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_OVERFLOW)); - } - } - - public bool OutOfRange - { - get { return ((this.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)); - } - } - - public bool BadReference - { - get { return ((this.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)); - } - } - - public bool Oscillatory - { - get { return ((this.value & QUALITY_DETAIL_OSCILLATORY) != 0);} - set { - if (value) - this.value |= QUALITY_DETAIL_OSCILLATORY; - else - this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_OSCILLATORY)); - } - } - - public bool Failure - { - get { return ((this.value & QUALITY_DETAIL_FAILURE) != 0);} - set { - if (value) - this.value |= QUALITY_DETAIL_FAILURE; - else - this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_FAILURE)); - } - } - - public bool OldData - { - get { return ((this.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)); - } - } - - public bool Inconsistent - { - get { return ((this.value & QUALITY_DETAIL_INCONSISTENT) != 0);} - set { - if (value) - this.value |= QUALITY_DETAIL_INCONSISTENT; - else - this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_INCONSISTENT)); - } - } - - public bool Inaccurate - { - get { return ((this.value & QUALITY_DETAIL_INACCURATE) != 0);} - set { - if (value) - this.value |= QUALITY_DETAIL_INACCURATE; - else - this.value = (ushort) ((int) this.value & (~QUALITY_DETAIL_INACCURATE)); - } - } - - public bool Substituted - { - get { return ((this.value & QUALITY_SOURCE_SUBSTITUTED) != 0);} - set { - if (value) - this.value |= QUALITY_SOURCE_SUBSTITUTED; - else - this.value = (ushort) ((int) this.value & (~QUALITY_SOURCE_SUBSTITUTED)); - } - } - - public bool Test - { - get { return ((this.value & QUALITY_TEST) != 0);} - set { - if (value) - this.value |= QUALITY_TEST; - else - this.value = (ushort) ((int) this.value & (~QUALITY_TEST)); - } - } - - public bool OperatorBlocked - { - get { return ((this.value & QUALITY_OPERATOR_BLOCKED) != 0);} - set { - if (value) - this.value |= QUALITY_OPERATOR_BLOCKED; - else - this.value = (ushort) ((int) this.value & (~QUALITY_OPERATOR_BLOCKED)); - } - } - - public bool Derived - { - get { return ((this.value & QUALITY_DERIVED) != 0); } - set { - if (value) - this.value |= QUALITY_DERIVED; - else - this.value = (ushort) ((int) this.value & (~QUALITY_DERIVED)); - } - } - } - - /// - /// Timestamp (represents IEC 61850 timestamps e.g. "t" attribute) - /// - public class Timestamp - { - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void Timestamp_clearFlags (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - static extern bool Timestamp_isLeapSecondKnown (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void Timestamp_setClockNotSynchronized (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void Timestamp_setTimeInMilliseconds (IntPtr self, UInt64 millisSinceEpoch); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 Timestamp_getTimeInSeconds (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt64 Timestamp_getTimeInMs (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void Timestamp_setByMmsUtcTime (IntPtr self, IntPtr mmsValue); + /// + /// MMS data access error for MmsValue type MMS_DATA_ACCESS_ERROR + /// + public enum MmsDataAccessError + { + NO_RESPONSE = -2, /* for server internal purposes only! */ + SUCCESS = -1, + OBJECT_INVALIDATED = 0, + HARDWARE_FAULT = 1, + TEMPORARILY_UNAVAILABLE = 2, + OBJECT_ACCESS_DENIED = 3, + OBJECT_UNDEFINED = 4, + INVALID_ADDRESS = 5, + TYPE_UNSUPPORTED = 6, + TYPE_INCONSISTENT = 7, + OBJECT_ATTRIBUTE_INCONSISTENT = 8, + OBJECT_ACCESS_UNSUPPORTED = 9, + OBJECT_NONE_EXISTENT = 10, + OBJECT_VALUE_INVALID = 11, + UNKNOWN = 12, + } + + [Flags] + public enum TriggerOptions + { + NONE = 0, + /** send report when value of data changed */ + DATA_CHANGED = 1, + /** send report when quality of data changed */ + QUALITY_CHANGED = 2, + /** send report when data or quality is updated */ + DATA_UPDATE = 4, + /** periodic transmission of all data set values */ + INTEGRITY = 8, + /** general interrogation (on client request) */ + GI = 16, + /** Report will be triggered only on rising edge (transient variable) */ + TRG_OPT_TRANSIENT = 128 + } + + /// + /// SmpMod values + /// + public enum SmpMod + { + SAMPLES_PER_PERIOD = 0, + SAMPLES_PER_SECOND = 1, + SECONDS_PER_SAMPLE = 2 + } + + /// + /// Values for Sampled Values (SV) OptFlds + /// + [Flags] + public enum SVOptions + { + NONE = 0, + REFRESH_TIME = 1, + SAMPLE_SYNC = 2, + SAMPLE_RATE = 4, + DATA_SET = 8, + SECURITY = 16, + ALL = 31 + } + + [Flags] + public enum ReportOptions + { + NONE = 0, + SEQ_NUM = 1, + TIME_STAMP = 2, + REASON_FOR_INCLUSION = 4, + DATA_SET = 8, + DATA_REFERENCE = 16, + BUFFER_OVERFLOW = 32, + ENTRY_ID = 64, + CONF_REV = 128, + SEGMENTATION = 256, + ALL = SEQ_NUM | TIME_STAMP | REASON_FOR_INCLUSION | DATA_SET | DATA_REFERENCE | + BUFFER_OVERFLOW | ENTRY_ID | CONF_REV | SEGMENTATION + } + + public enum Validity + { + GOOD = 0, + RESERVED = 1, + INVALID = 2, + QUESTIONABLE = 3 + } + + /// + /// The quality of a data object. + /// + public class Quality + { + private UInt16 value; + + private const UInt16 QUALITY_DETAIL_OVERFLOW = 4; + private const UInt16 QUALITY_DETAIL_OUT_OF_RANGE = 8; + private const UInt16 QUALITY_DETAIL_BAD_REFERENCE = 16; + private const UInt16 QUALITY_DETAIL_OSCILLATORY = 32; + private const UInt16 QUALITY_DETAIL_FAILURE = 64; + private const UInt16 QUALITY_DETAIL_OLD_DATA = 128; + private const UInt16 QUALITY_DETAIL_INCONSISTENT = 256; + private const UInt16 QUALITY_DETAIL_INACCURATE = 512; + private const UInt16 QUALITY_SOURCE_SUBSTITUTED = 1024; + private const UInt16 QUALITY_TEST = 2048; + private const UInt16 QUALITY_OPERATOR_BLOCKED = 4096; + private const UInt16 QUALITY_DERIVED = 8192; + + public ushort Value => value; + + public override string ToString() + { + return GetValidity().ToString(); + + } + + public Quality(int bitStringValue) + { + value = (UInt16)bitStringValue; + } + + public Quality() + { + value = 0; + } + + public Validity GetValidity() + { + int qualityVal = value & 0x3; + + return (Validity)qualityVal; + } + + public void SetValidity(Validity validity) + { + value = (UInt16)(value & 0xfffc); + + value += (ushort)validity; + } + + public Validity Validity + { + get { return GetValidity(); } + set { SetValidity(value); } + } + + public bool Overflow + { + get { return ((value & QUALITY_DETAIL_OVERFLOW) != 0); } + set + { + if (value) + this.value |= QUALITY_DETAIL_OVERFLOW; + else + this.value = (ushort)(this.value & (~QUALITY_DETAIL_OVERFLOW)); + } + } + + public bool OutOfRange + { + get { return ((value & QUALITY_DETAIL_OUT_OF_RANGE) != 0); } + set + { + if (value) + this.value |= QUALITY_DETAIL_OUT_OF_RANGE; + else + this.value = (ushort)(this.value & (~QUALITY_DETAIL_OUT_OF_RANGE)); + } + } + + public bool BadReference + { + get { return ((value & QUALITY_DETAIL_BAD_REFERENCE) != 0); } + set + { + if (value) + this.value |= QUALITY_DETAIL_BAD_REFERENCE; + else + this.value = (ushort)(this.value & (~QUALITY_DETAIL_BAD_REFERENCE)); + } + } + + public bool Oscillatory + { + get { return ((value & QUALITY_DETAIL_OSCILLATORY) != 0); } + set + { + if (value) + this.value |= QUALITY_DETAIL_OSCILLATORY; + else + this.value = (ushort)(this.value & (~QUALITY_DETAIL_OSCILLATORY)); + } + } + + public bool Failure + { + get { return ((value & QUALITY_DETAIL_FAILURE) != 0); } + set + { + if (value) + this.value |= QUALITY_DETAIL_FAILURE; + else + this.value = (ushort)(this.value & (~QUALITY_DETAIL_FAILURE)); + } + } + + public bool OldData + { + get { return ((value & QUALITY_DETAIL_OLD_DATA) != 0); } + set + { + if (value) + this.value |= QUALITY_DETAIL_OLD_DATA; + else + this.value = (ushort)(this.value & (~QUALITY_DETAIL_OLD_DATA)); + } + } + + public bool Inconsistent + { + get { return ((value & QUALITY_DETAIL_INCONSISTENT) != 0); } + set + { + if (value) + this.value |= QUALITY_DETAIL_INCONSISTENT; + else + this.value = (ushort)(this.value & (~QUALITY_DETAIL_INCONSISTENT)); + } + } + + public bool Inaccurate + { + get { return ((value & QUALITY_DETAIL_INACCURATE) != 0); } + set + { + if (value) + this.value |= QUALITY_DETAIL_INACCURATE; + else + this.value = (ushort)(this.value & (~QUALITY_DETAIL_INACCURATE)); + } + } + + public bool Substituted + { + get { return ((value & QUALITY_SOURCE_SUBSTITUTED) != 0); } + set + { + if (value) + this.value |= QUALITY_SOURCE_SUBSTITUTED; + else + this.value = (ushort)(this.value & (~QUALITY_SOURCE_SUBSTITUTED)); + } + } + + public bool Test + { + get { return ((value & QUALITY_TEST) != 0); } + set + { + if (value) + this.value |= QUALITY_TEST; + else + this.value = (ushort)(this.value & (~QUALITY_TEST)); + } + } + + public bool OperatorBlocked + { + get { return ((value & QUALITY_OPERATOR_BLOCKED) != 0); } + set + { + if (value) + this.value |= QUALITY_OPERATOR_BLOCKED; + else + this.value = (ushort)(this.value & (~QUALITY_OPERATOR_BLOCKED)); + } + } + + public bool Derived + { + get { return ((value & QUALITY_DERIVED) != 0); } + set + { + if (value) + this.value |= QUALITY_DERIVED; + else + this.value = (ushort)(this.value & (~QUALITY_DERIVED)); + } + } + } + + /// + /// Timestamp (represents IEC 61850 timestamps e.g. "t" attribute) + /// + public class Timestamp + { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void Timestamp_clearFlags(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool Timestamp_isLeapSecondKnown(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void Timestamp_setClockNotSynchronized(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void Timestamp_setTimeInMilliseconds(IntPtr self, UInt64 millisSinceEpoch); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 Timestamp_getTimeInSeconds(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt64 Timestamp_getTimeInMs(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void Timestamp_setByMmsUtcTime(IntPtr self, IntPtr mmsValue); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 Timestamp_getFractionOfSecondPart(IntPtr self); @@ -436,266 +453,278 @@ namespace IEC61850 static extern float Timestamp_getFractionOfSecond(IntPtr self); internal IntPtr self = IntPtr.Zero; - private bool responsibleForDeletion; - - internal Timestamp(IntPtr timestampRef, bool selfAllocated) - { - this.self = timestampRef; - this.responsibleForDeletion = selfAllocated; - } - - public Timestamp (DateTime timestamp) : this () - { - SetDateTime (timestamp); - } - - public Timestamp (MmsValue mmsUtcTime) : this() - { - SetByMmsUtcTime (mmsUtcTime); - } - - /// - /// Initializes a new instance of the class. - /// - public Timestamp() - { - self = Timestamp_create (); - LeapSecondKnown = true; - responsibleForDeletion = true; - } - - /// - /// Initializes a new instance of the class. - /// - public Timestamp(Timestamp other) : this() - { - SetTimeInSeconds (other.GetTimeInSeconds ()); - SetSubsecondPrecision (other.GetSubsecondPrecision ()); - SetFractionOfSecondPart (other.GetFractionOfSecondPart ()); - SetLeapSecondKnow(other.IsLeapSecondKnown()); - SetClockFailure(other.HasClockFailure()); - SetClockNotSynchronized(other.IsClockNotSynchronized()); - } - - public Timestamp(byte[] value) - { - self = Timestamp_createFromByteArray (value); - responsibleForDeletion = true; - } - - ~Timestamp () - { - if (responsibleForDeletion) - Timestamp_destroy (self); - } - - public void ClearFlags() - { - Timestamp_clearFlags (self); - } - - public void SetDateTime(DateTime timestamp) - { - DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - DateTime timestampUTC = timestamp.ToUniversalTime(); - - TimeSpan timeDiff = timestampUTC - epoch; - ulong timeVal = Convert.ToUInt64(timeDiff.TotalMilliseconds); - - SetTimeInMilliseconds (timeVal); - } - - public bool LeapSecondKnown { - get { return IsLeapSecondKnown ();} - set { SetLeapSecondKnow (value);} - } - - public bool IsLeapSecondKnown() - { - return Timestamp_isLeapSecondKnown (self); - } - - public void SetLeapSecondKnow(bool value) - { - Timestamp_setLeapSecondKnown (self, value); - } - - public bool ClockFailure { - get { return HasClockFailure ();} - set { SetClockFailure (value);} - } - - public bool HasClockFailure() - { - return Timestamp_hasClockFailure (self); - } - - public void SetClockFailure(bool value) - { - Timestamp_setClockFailure (self, value); - } - - public bool ClockNotSynchronized { - get { return IsClockNotSynchronized (); } - set { SetClockNotSynchronized (value); } - } - - public bool IsClockNotSynchronized() { - return Timestamp_isClockNotSynchronized(self); - } - - public void SetClockNotSynchronized(bool value) { - Timestamp_setClockNotSynchronized (self, value); - } - - public int SubsecondPrecision { - get { return GetSubsecondPrecision (); } - set { SetSubsecondPrecision (value); } - } - - public int GetSubsecondPrecision() { - return Timestamp_getSubsecondPrecision (self); - } - - public void SetSubsecondPrecision(int subsecondPrecision) { - Timestamp_setSubsecondPrecision (self, subsecondPrecision); - } - - public UInt32 TimeInSeconds { - get { return GetTimeInSeconds (); } - set { SetTimeInSeconds (value); } - } - - public UInt32 GetTimeInSeconds() - { - return Timestamp_getTimeInSeconds (self); - } - - public void SetTimeInSeconds(UInt32 secondsSinceEpoch) - { - Timestamp_setTimeInSeconds (self, secondsSinceEpoch); - } - - public UInt64 TimeInMilliseconds { - get { return GetTimeInMilliseconds (); } - set { SetTimeInMilliseconds (value); } - } - - public UInt64 GetTimeInMilliseconds() - { - return Timestamp_getTimeInMs (self); - } - - public void SetTimeInMilliseconds(UInt64 millisSinceEpoch) { - Timestamp_setTimeInMilliseconds (self, millisSinceEpoch); - } - - public void SetByMmsUtcTime(MmsValue mmsValue) - { - 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 ()); - - return retVal; - } - - public UInt32 GetFractionOfSecondPart() - { - return Timestamp_getFractionOfSecondPart(self); - } - - public void SetFractionOfSecondPart(UInt32 fractionOfSecond) - { - Timestamp_setFractionOfSecondPart(self, fractionOfSecond); - } - - public float GetFractionOfSecond() - { - return Timestamp_getFractionOfSecond(self); - } - - } + private bool responsibleForDeletion; + + internal Timestamp(IntPtr timestampRef, bool selfAllocated) + { + self = timestampRef; + responsibleForDeletion = selfAllocated; + } + + public Timestamp(DateTime timestamp) : this() + { + SetDateTime(timestamp); + } + + public Timestamp(MmsValue mmsUtcTime) : this() + { + SetByMmsUtcTime(mmsUtcTime); + } + + /// + /// Initializes a new instance of the class. + /// + public Timestamp() + { + self = Timestamp_create(); + LeapSecondKnown = true; + responsibleForDeletion = true; + } + + /// + /// Initializes a new instance of the class. + /// + public Timestamp(Timestamp other) : this() + { + SetTimeInSeconds(other.GetTimeInSeconds()); + SetSubsecondPrecision(other.GetSubsecondPrecision()); + SetFractionOfSecondPart(other.GetFractionOfSecondPart()); + SetLeapSecondKnow(other.IsLeapSecondKnown()); + SetClockFailure(other.HasClockFailure()); + SetClockNotSynchronized(other.IsClockNotSynchronized()); + } + + public Timestamp(byte[] value) + { + self = Timestamp_createFromByteArray(value); + responsibleForDeletion = true; + } + + ~Timestamp() + { + if (responsibleForDeletion) + Timestamp_destroy(self); + } + + public void ClearFlags() + { + Timestamp_clearFlags(self); + } + + public void SetDateTime(DateTime timestamp) + { + DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + DateTime timestampUTC = timestamp.ToUniversalTime(); + + TimeSpan timeDiff = timestampUTC - epoch; + ulong timeVal = Convert.ToUInt64(timeDiff.TotalMilliseconds); + + SetTimeInMilliseconds(timeVal); + } + + public bool LeapSecondKnown + { + get { return IsLeapSecondKnown(); } + set { SetLeapSecondKnow(value); } + } + + public bool IsLeapSecondKnown() + { + return Timestamp_isLeapSecondKnown(self); + } + + public void SetLeapSecondKnow(bool value) + { + Timestamp_setLeapSecondKnown(self, value); + } + + public bool ClockFailure + { + get { return HasClockFailure(); } + set { SetClockFailure(value); } + } + + public bool HasClockFailure() + { + return Timestamp_hasClockFailure(self); + } + + public void SetClockFailure(bool value) + { + Timestamp_setClockFailure(self, value); + } + + public bool ClockNotSynchronized + { + get { return IsClockNotSynchronized(); } + set { SetClockNotSynchronized(value); } + } + + public bool IsClockNotSynchronized() + { + return Timestamp_isClockNotSynchronized(self); + } + + public void SetClockNotSynchronized(bool value) + { + Timestamp_setClockNotSynchronized(self, value); + } + + public int SubsecondPrecision + { + get { return GetSubsecondPrecision(); } + set { SetSubsecondPrecision(value); } + } + + public int GetSubsecondPrecision() + { + return Timestamp_getSubsecondPrecision(self); + } + + public void SetSubsecondPrecision(int subsecondPrecision) + { + Timestamp_setSubsecondPrecision(self, subsecondPrecision); + } + + public UInt32 TimeInSeconds + { + get { return GetTimeInSeconds(); } + set { SetTimeInSeconds(value); } + } + + public UInt32 GetTimeInSeconds() + { + return Timestamp_getTimeInSeconds(self); + } + + public void SetTimeInSeconds(UInt32 secondsSinceEpoch) + { + Timestamp_setTimeInSeconds(self, secondsSinceEpoch); + } + + public UInt64 TimeInMilliseconds + { + get { return GetTimeInMilliseconds(); } + set { SetTimeInMilliseconds(value); } + } + + public UInt64 GetTimeInMilliseconds() + { + return Timestamp_getTimeInMs(self); + } + + public void SetTimeInMilliseconds(UInt64 millisSinceEpoch) + { + Timestamp_setTimeInMilliseconds(self, millisSinceEpoch); + } + + public void SetByMmsUtcTime(MmsValue mmsValue) + { + Timestamp_setByMmsUtcTime(self, mmsValue.valueReference); + } + + public DateTime AsDateTime() + { + DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + DateTime retVal = epoch.AddMilliseconds(GetTimeInMilliseconds()); + + return retVal; + } + + public UInt32 GetFractionOfSecondPart() + { + return Timestamp_getFractionOfSecondPart(self); + } + + public void SetFractionOfSecondPart(UInt32 fractionOfSecond) + { + Timestamp_setFractionOfSecondPart(self, fractionOfSecond); + } + + public float GetFractionOfSecond() + { + return Timestamp_getFractionOfSecond(self); + } + + } public enum ACSIClass - { - /** data objects */ - ACSI_CLASS_DATA_OBJECT, - /** data sets (container for multiple data objects) */ - ACSI_CLASS_DATA_SET, - /** buffered report control blocks */ - ACSI_CLASS_BRCB, - /** unbuffered report control blocks */ - ACSI_CLASS_URCB, - /** log control blocks */ - ACSI_CLASS_LCB, - /** logs (journals) */ - ACSI_CLASS_LOG, - /** setting group control blocks */ - ACSI_CLASS_SGCB, - /** GOOSE control blocks */ - ACSI_CLASS_GoCB, - /** GSE control blocks */ - ACSI_CLASS_GsCB, - /** multicast sampled values control blocks */ - ACSI_CLASS_MSVCB, - /** unicast sampled values control blocks */ - ACSI_CLASS_USVCB - } - - public enum FunctionalConstraint - { - /** Status information */ - ST = 0, - /** Measurands - analog values */ - MX = 1, - /** Setpoint */ - SP = 2, - /** Substitution */ - SV = 3, - /** Configuration */ - CF = 4, - /** Description */ - DC = 5, - /** Setting group */ - SG = 6, - /** Setting group editable */ - SE = 7, - /** Service response / Service tracking */ - SR = 8, - /** Operate received */ - OR = 9, - /** Blocking */ - BL = 10, - /** Extended definition */ - EX = 11, - /** Control */ - CO = 12, - /** Unicast SV */ - US = 13, - /** Multicast SV */ - MS = 14, - /** Unbuffered report */ - RP = 15, - /** Buffered report */ - BR = 16, - /** Log control blocks */ - LG = 17, - - /** All FCs - wildcard value */ - ALL = 99, - NONE = -1 - } + { + /** data objects */ + ACSI_CLASS_DATA_OBJECT, + /** data sets (container for multiple data objects) */ + ACSI_CLASS_DATA_SET, + /** buffered report control blocks */ + ACSI_CLASS_BRCB, + /** unbuffered report control blocks */ + ACSI_CLASS_URCB, + /** log control blocks */ + ACSI_CLASS_LCB, + /** logs (journals) */ + ACSI_CLASS_LOG, + /** setting group control blocks */ + ACSI_CLASS_SGCB, + /** GOOSE control blocks */ + ACSI_CLASS_GoCB, + /** GSE control blocks */ + ACSI_CLASS_GsCB, + /** multicast sampled values control blocks */ + ACSI_CLASS_MSVCB, + /** unicast sampled values control blocks */ + ACSI_CLASS_USVCB + } + + public enum FunctionalConstraint + { + /** Status information */ + ST = 0, + /** Measurands - analog values */ + MX = 1, + /** Setpoint */ + SP = 2, + /** Substitution */ + SV = 3, + /** Configuration */ + CF = 4, + /** Description */ + DC = 5, + /** Setting group */ + SG = 6, + /** Setting group editable */ + SE = 7, + /** Service response / Service tracking */ + SR = 8, + /** Operate received */ + OR = 9, + /** Blocking */ + BL = 10, + /** Extended definition */ + EX = 11, + /** Control */ + CO = 12, + /** Unicast SV */ + US = 13, + /** Multicast SV */ + MS = 14, + /** Unbuffered report */ + RP = 15, + /** Buffered report */ + BR = 16, + /** Log control blocks */ + LG = 17, + + /** All FCs - wildcard value */ + ALL = 99, + NONE = -1 + } /// /// Definition for LastAppError error type for control models /// Used in LastApplError and CommandTermination messages. /// - public enum ControlLastApplError { + public enum ControlLastApplError + { NO_ERROR = 0, UNKNOWN = 1, TIMEOUT_TEST = 2, @@ -706,90 +735,92 @@ namespace IEC61850 /// AddCause - additional cause information for control model errors /// Used in LastApplError and CommandTermination messages. /// - public enum ControlAddCause { - ADD_CAUSE_UNKNOWN = 0, - ADD_CAUSE_NOT_SUPPORTED = 1, - ADD_CAUSE_BLOCKED_BY_SWITCHING_HIERARCHY = 2, - ADD_CAUSE_SELECT_FAILED = 3, - ADD_CAUSE_INVALID_POSITION = 4, - ADD_CAUSE_POSITION_REACHED = 5, - ADD_CAUSE_PARAMETER_CHANGE_IN_EXECUTION = 6, - ADD_CAUSE_STEP_LIMIT = 7, - ADD_CAUSE_BLOCKED_BY_MODE = 8, - ADD_CAUSE_BLOCKED_BY_PROCESS = 9, - ADD_CAUSE_BLOCKED_BY_INTERLOCKING = 10, - ADD_CAUSE_BLOCKED_BY_SYNCHROCHECK = 11, - ADD_CAUSE_COMMAND_ALREADY_IN_EXECUTION = 12, - ADD_CAUSE_BLOCKED_BY_HEALTH = 13, - ADD_CAUSE_1_OF_N_CONTROL = 14, - ADD_CAUSE_ABORTION_BY_CANCEL = 15, - ADD_CAUSE_TIME_LIMIT_OVER = 16, - ADD_CAUSE_ABORTION_BY_TRIP = 17, - ADD_CAUSE_OBJECT_NOT_SELECTED = 18, - ADD_CAUSE_OBJECT_ALREADY_SELECTED = 19, - ADD_CAUSE_NO_ACCESS_AUTHORITY = 20, - ADD_CAUSE_ENDED_WITH_OVERSHOOT = 21, - ADD_CAUSE_ABORTION_DUE_TO_DEVIATION = 22, - ADD_CAUSE_ABORTION_BY_COMMUNICATION_LOSS = 23, - ADD_CAUSE_ABORTION_BY_COMMAND = 24, - ADD_CAUSE_NONE = 25, - ADD_CAUSE_INCONSISTENT_PARAMETERS = 26, - ADD_CAUSE_LOCKED_BY_OTHER_CLIENT = 27 - } - - /// - /// Object reference. Helper function to handle object reference strings. - /// - public static class ObjectReference { - - /// - /// Get the name part of an object reference with appended FC - /// - /// - /// The element name. - /// - /// - /// Object reference with appended fc. - /// - public static string getElementName (string objectReferenceWithFc) - { - int fcPartStartIndex = objectReferenceWithFc.IndexOf('['); - - if (fcPartStartIndex == -1) - return objectReferenceWithFc; - - return objectReferenceWithFc.Substring(0, fcPartStartIndex); - } - - /// - /// Get the FC of an object reference with appended FC. - /// - /// - /// The FC - /// - /// - /// Object reference with FC. - /// - public static FunctionalConstraint getFC (string objectReferenceWithFc) - { - int fcPartStartIndex = objectReferenceWithFc.IndexOf('['); - - if (fcPartStartIndex == -1) - return FunctionalConstraint.NONE; - - string fcString = objectReferenceWithFc.Substring(fcPartStartIndex + 1 , 2); - - try - { - return (FunctionalConstraint) Enum.Parse(typeof(FunctionalConstraint), fcString); - } - catch(ArgumentException) - { - return FunctionalConstraint.NONE; - } - } - } - - } + public enum ControlAddCause + { + ADD_CAUSE_UNKNOWN = 0, + ADD_CAUSE_NOT_SUPPORTED = 1, + ADD_CAUSE_BLOCKED_BY_SWITCHING_HIERARCHY = 2, + ADD_CAUSE_SELECT_FAILED = 3, + ADD_CAUSE_INVALID_POSITION = 4, + ADD_CAUSE_POSITION_REACHED = 5, + ADD_CAUSE_PARAMETER_CHANGE_IN_EXECUTION = 6, + ADD_CAUSE_STEP_LIMIT = 7, + ADD_CAUSE_BLOCKED_BY_MODE = 8, + ADD_CAUSE_BLOCKED_BY_PROCESS = 9, + ADD_CAUSE_BLOCKED_BY_INTERLOCKING = 10, + ADD_CAUSE_BLOCKED_BY_SYNCHROCHECK = 11, + ADD_CAUSE_COMMAND_ALREADY_IN_EXECUTION = 12, + ADD_CAUSE_BLOCKED_BY_HEALTH = 13, + ADD_CAUSE_1_OF_N_CONTROL = 14, + ADD_CAUSE_ABORTION_BY_CANCEL = 15, + ADD_CAUSE_TIME_LIMIT_OVER = 16, + ADD_CAUSE_ABORTION_BY_TRIP = 17, + ADD_CAUSE_OBJECT_NOT_SELECTED = 18, + ADD_CAUSE_OBJECT_ALREADY_SELECTED = 19, + ADD_CAUSE_NO_ACCESS_AUTHORITY = 20, + ADD_CAUSE_ENDED_WITH_OVERSHOOT = 21, + ADD_CAUSE_ABORTION_DUE_TO_DEVIATION = 22, + ADD_CAUSE_ABORTION_BY_COMMUNICATION_LOSS = 23, + ADD_CAUSE_ABORTION_BY_COMMAND = 24, + ADD_CAUSE_NONE = 25, + ADD_CAUSE_INCONSISTENT_PARAMETERS = 26, + ADD_CAUSE_LOCKED_BY_OTHER_CLIENT = 27 + } + + /// + /// Object reference. Helper function to handle object reference strings. + /// + public static class ObjectReference + { + + /// + /// Get the name part of an object reference with appended FC + /// + /// + /// The element name. + /// + /// + /// Object reference with appended fc. + /// + public static string getElementName(string objectReferenceWithFc) + { + int fcPartStartIndex = objectReferenceWithFc.IndexOf('['); + + if (fcPartStartIndex == -1) + return objectReferenceWithFc; + + return objectReferenceWithFc.Substring(0, fcPartStartIndex); + } + + /// + /// Get the FC of an object reference with appended FC. + /// + /// + /// The FC + /// + /// + /// Object reference with FC. + /// + public static FunctionalConstraint getFC(string objectReferenceWithFc) + { + int fcPartStartIndex = objectReferenceWithFc.IndexOf('['); + + if (fcPartStartIndex == -1) + return FunctionalConstraint.NONE; + + string fcString = objectReferenceWithFc.Substring(fcPartStartIndex + 1, 2); + + try + { + return (FunctionalConstraint)Enum.Parse(typeof(FunctionalConstraint), fcString); + } + catch (ArgumentException) + { + return FunctionalConstraint.NONE; + } + } + } + + } } diff --git a/dotnet/IEC61850forCSharp/IEC61850Model/SVControlBlock.cs b/dotnet/IEC61850forCSharp/IEC61850Model/SVControlBlock.cs index 9e5423f1..9d932b99 100644 --- a/dotnet/IEC61850forCSharp/IEC61850Model/SVControlBlock.cs +++ b/dotnet/IEC61850forCSharp/IEC61850Model/SVControlBlock.cs @@ -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; } @@ -91,5 +89,5 @@ namespace IEC61850 } } - + } diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs index 8f321fce..44f36a05 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs @@ -1,7 +1,7 @@ /* * IEC61850ServerAPI.cs * - * Copyright 2016-2024 Michael Zillgith + * Copyright 2016-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -42,13 +42,14 @@ namespace IEC61850 static extern IntPtr ConfigFileParser_createModelFromConfigFileEx(string filename); public static IedModel CreateModelFromConfigFile(string filePath) - { - IntPtr retVal = ConfigFileParser_createModelFromConfigFileEx (filePath); - if (retVal == IntPtr.Zero) { + { + IntPtr retVal = ConfigFileParser_createModelFromConfigFileEx(filePath); + if (retVal == IntPtr.Zero) + { return null; } - return new IedModel (retVal); + return new IedModel(retVal); } } @@ -102,7 +103,7 @@ namespace IEC61850 ~IedModel() { - Dispose(); + Dispose(); } /// @@ -283,7 +284,7 @@ namespace IEC61850 if (nodeRef == IntPtr.Zero) return null; - return GetModelNodeFromNodeRef (nodeRef); + return GetModelNodeFromNodeRef(nodeRef); } /// @@ -298,7 +299,7 @@ namespace IEC61850 if (nodeRef == IntPtr.Zero) return null; - return GetModelNodeFromNodeRef (nodeRef); + return GetModelNodeFromNodeRef(nodeRef); } public SVControlBlock GetSVControlBlock(LogicalNode logicalNode, string svcbName) @@ -329,9 +330,9 @@ namespace IEC61850 public IedModel IedModel { get; } - public LogicalDevice (IntPtr self, IedModel iedModel) : base (self) + public LogicalDevice(IntPtr self, IedModel iedModel) : base(self) { - this.IedModel = iedModel; + IedModel = iedModel; } /// @@ -341,7 +342,7 @@ namespace IEC61850 /// Model containing this logical device public LogicalDevice(string inst, IedModel parent) { - this.IedModel = parent; + IedModel = parent; self = LogicalDevice_create(inst, parent.self); } @@ -354,7 +355,7 @@ namespace IEC61850 /// LD name (for functional naming). When set, the exernally visible domain name for this LD public LogicalDevice(string inst, IedModel parent, string ldName) { - this.IedModel = parent; + IedModel = parent; self = LogicalDevice_createEx(inst, parent.self, ldName); } @@ -365,9 +366,9 @@ namespace IEC61850 /// the SGCB instance or NULL if no SGCB is available public SettingGroupControlBlock GetSettingGroupControlBlock() { - IntPtr sgcb = LogicalDevice_getSettingGroupControlBlock(this.self); + IntPtr sgcb = LogicalDevice_getSettingGroupControlBlock(self); - if(sgcb == IntPtr.Zero) + if (sgcb == IntPtr.Zero) return null; return new SettingGroupControlBlock(sgcb); @@ -384,7 +385,7 @@ namespace IEC61850 internal Dictionary rcbs = new Dictionary(); - public LogicalNode (IntPtr self, ModelNode parent) : base(self) + public LogicalNode(IntPtr self, ModelNode parent) : base(self) { this.parent = parent; } @@ -407,18 +408,20 @@ namespace IEC61850 } } - public enum AccessPolicy { + public enum AccessPolicy + { ACCESS_POLICY_ALLOW = 0, ACCESS_POLICY_DENY = 1 } - public enum DataAttributeType { + public enum DataAttributeType + { BOOLEAN = 0, INT8 = 1, INT16 = 2, INT32 = 3, - INT64 = 4, - INT128 = 5, + INT64 = 4, + INT128 = 5, INT8U = 6, INT16U = 7, INT24U = 8, @@ -466,7 +469,7 @@ namespace IEC61850 /// The CDC class contains helper functions to create DataObject instances for the /// most common Common Data Classes. /// - public class CDC + public class CDC { [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr CDC_SPS_create(string name, IntPtr parent, uint options); @@ -545,7 +548,7 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr CDC_APC_create(string name, IntPtr parent, uint options, uint controlOptions, [MarshalAs(UnmanagedType.I1)] bool isIntegerNotFloat); - + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr CDC_BCR_create(string name, IntPtr parent, uint options); @@ -593,11 +596,11 @@ namespace IEC61850 IntPtr self = CDC_SPS_create(name, parent.self, options); if (self != IntPtr.Zero) - return new DataObject (self, parent); + return new DataObject(self, parent); else return null; } - + public static DataObject Create_CDC_DPS(ModelNode parent, string name, uint options) { IntPtr self = CDC_DPS_create(name, parent.self, options); @@ -753,7 +756,7 @@ namespace IEC61850 IntPtr self = CDC_INS_create(name, parent.self, options); if (self != IntPtr.Zero) - return new DataObject (self, parent); + return new DataObject(self, parent); else return null; } @@ -763,7 +766,7 @@ namespace IEC61850 IntPtr self = CDC_MV_create(name, parent.self, options, isIntegerNotFloat); if (self != IntPtr.Zero) - return new DataObject (self, parent); + return new DataObject(self, parent); else return null; } @@ -773,7 +776,7 @@ namespace IEC61850 IntPtr self = CDC_INC_create(name, parent.self, options, controlOptions); if (self != IntPtr.Zero) - return new DataObject (self, parent); + return new DataObject(self, parent); else return null; } @@ -783,7 +786,7 @@ namespace IEC61850 IntPtr self = CDC_LPL_create(name, parent.self, options); if (self != IntPtr.Zero) - return new DataObject (self, parent); + return new DataObject(self, parent); else return null; } @@ -793,7 +796,7 @@ namespace IEC61850 IntPtr self = CDC_DPL_create(name, parent.self, options); if (self != IntPtr.Zero) - return new DataObject (self, parent); + return new DataObject(self, parent); else return null; } @@ -933,7 +936,7 @@ namespace IEC61850 { [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr DataObject_create(string name, IntPtr parent, int arrayElements); - + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ModelNode_getChildWithFc(IntPtr self, string objectReference, int fc); @@ -950,7 +953,7 @@ namespace IEC61850 { this.parent = parent; - self = DataObject_create (name, parent.self, arrayElements); + self = DataObject_create(name, parent.self, arrayElements); } /// @@ -965,7 +968,7 @@ namespace IEC61850 public DataAttribute GetChildWithFc(string objRef, FunctionalConstraint fc) { DataAttribute dataAttribute = null; - IntPtr da = ModelNode_getChildWithFc(this.self, objRef, (int)fc); + IntPtr da = ModelNode_getChildWithFc(self, objRef, (int)fc); if (da != IntPtr.Zero) { @@ -1011,12 +1014,12 @@ namespace IEC61850 /// the trigger options (dupd, dchg, qchg) that cause an event notification /// the number of array elements if the data attribute is an array or 0 /// an optional short address (deprecated) - public DataAttribute (string name, ModelNode parent, DataAttributeType type, FunctionalConstraint fc, TriggerOptions trgOps, + public DataAttribute(string name, ModelNode parent, DataAttributeType type, FunctionalConstraint fc, TriggerOptions trgOps, int arrayElements, UInt32 sAddr) { this.parent = parent; - self = DataAttribute_create (name, parent.self, (int)type, (int)fc, (byte)trgOps, arrayElements, sAddr); + self = DataAttribute_create(name, parent.self, (int)type, (int)fc, (byte)trgOps, arrayElements, sAddr); } /// @@ -1152,7 +1155,7 @@ namespace IEC61850 } else { - if (this.parent != null) + if (parent != null) return parent.GetIedModel(); else return null; @@ -1292,7 +1295,7 @@ namespace IEC61850 if (childNode == null) { - childNode = ModelNode.CreateInstance(modelNodePtr, this); + childNode = ModelNode.CreateInstance(modelNodePtr, this); if ((childNode != null) && (iedModel != null)) { @@ -1324,14 +1327,16 @@ namespace IEC61850 IntPtr objRefPtr = ModelNode_getObjectReferenceEx(self, nativeMemory, withoutIedName); - if (objRefPtr != IntPtr.Zero) { + if (objRefPtr != IntPtr.Zero) + { string objRef = Marshal.PtrToStringAnsi(objRefPtr); Marshal.FreeHGlobal(nativeMemory); return objRef; } - else { + else + { Marshal.FreeHGlobal(nativeMemory); return null; @@ -1738,17 +1743,20 @@ namespace IEC61850 public SettingGroupControlBlock(LogicalNode parent, UInt32 actSG, UInt32 numOfSGs) { - self = SettingGroupControlBlock_create(parent.self, (byte) actSG, (byte) numOfSGs); + self = SettingGroupControlBlock_create(parent.self, (byte)actSG, (byte)numOfSGs); } public SettingGroupControlBlock(IntPtr self) { - this.self = self ; + this.self = self; } } public class ClientConnection : IDisposable { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientConnection_getSecurityToken(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ClientConnection_getPeerAddress(IntPtr self); @@ -1772,6 +1780,31 @@ namespace IEC61850 this.self = ClientConnection_claimOwnership(self); } + /// + /// Get the security token associated with this connection + /// The security token is an opaque handle that is associated with the connection.It is provided by the + /// authenticator (if one is present). If no security token is used then this function returns NULL + /// + /// the security token or NULL + public object GetSecurityToken() + { + lock (this) + { + if (self != IntPtr.Zero) + { + IntPtr token = ClientConnection_getSecurityToken(self); + + if (token != IntPtr.Zero) + { + GCHandle handle = GCHandle.FromIntPtr(token); + return handle; + } + } + } + + return null; + } + public string GetPeerAddress() { lock (this) @@ -1834,7 +1867,7 @@ namespace IEC61850 } } - ~ClientConnection () + ~ClientConnection() { Dispose(); } @@ -1884,7 +1917,7 @@ namespace IEC61850 if (lnModelNode != null && lnModelNode is LogicalNode) { - this.ln = lnModelNode as LogicalNode; + ln = lnModelNode as LogicalNode; } } @@ -1961,17 +1994,17 @@ namespace IEC61850 /// public class ControlAction { - [DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ControlAction_setAddCause (IntPtr self, int addCause); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ControlAction_setAddCause(IntPtr self, int addCause); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ControlAction_setError(IntPtr self, int error); - [DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern int ControlAction_getOrCat (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int ControlAction_getOrCat(IntPtr self); - [DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ControlAction_getOrIdent (IntPtr self, ref int size); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ControlAction_getOrIdent(IntPtr self, ref int size); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ControlAction_getClientConnection(IntPtr self); @@ -2001,7 +2034,7 @@ namespace IEC61850 private IedServer.ControlHandlerInfo info; private IedServer iedServer; - internal ControlAction (IntPtr self, IedServer.ControlHandlerInfo info, IedServer iedServer) + internal ControlAction(IntPtr self, IedServer.ControlHandlerInfo info, IedServer iedServer) { this.self = self; this.info = info; @@ -2021,36 +2054,36 @@ namespace IEC61850 /// Sets the add cause for the next command termination or application error message /// /// the additional cause code - public void SetAddCause (ControlAddCause addCause) + public void SetAddCause(ControlAddCause addCause) { - ControlAction_setAddCause (self, (int)addCause); + ControlAction_setAddCause(self, (int)addCause); } /// /// Gets the originator category provided by the client /// /// The or cat. - public OrCat GetOrCat () + public OrCat GetOrCat() { - return (OrCat)ControlAction_getOrCat (self); + return (OrCat)ControlAction_getOrCat(self); } /// /// Get the originator identifier provided by the client /// /// The or ident. - public byte [] GetOrIdent () + public byte[] GetOrIdent() { int size = 0; - IntPtr orIdentPtr = ControlAction_getOrIdent (self, ref size); + IntPtr orIdentPtr = ControlAction_getOrIdent(self, ref size); if (orIdentPtr == IntPtr.Zero) return null; - byte [] orIdent = new byte [size]; + byte[] orIdent = new byte[size]; - Marshal.Copy (orIdentPtr, orIdent, 0, size); + Marshal.Copy(orIdentPtr, orIdent, 0, size); return orIdent; } @@ -2068,7 +2101,7 @@ namespace IEC61850 /// Gets the control object that is subject to this action /// /// the controllable data object instance - public DataObject GetControlObject () + public DataObject GetControlObject() { return info.controlObject; } @@ -2095,14 +2128,15 @@ namespace IEC61850 /// Gets the client object associated with the client that caused the control action /// /// The client connection. - public ClientConnection GetClientConnection () + public ClientConnection GetClientConnection() { ClientConnection con = null; - IntPtr conPtr = ControlAction_getClientConnection (self); + IntPtr conPtr = ControlAction_getClientConnection(self); - if (conPtr != IntPtr.Zero) { - iedServer.clientConnections.TryGetValue (conPtr, out con); + if (conPtr != IntPtr.Zero) + { + iedServer.clientConnections.TryGetValue(conPtr, out con); } return con; @@ -2191,7 +2225,7 @@ namespace IEC61850 public delegate void RCBEventHandler(object parameter, ReportControlBlock rcb, ClientConnection con, RCBEventType eventType, string parameterName, MmsDataAccessError serviceError); - public delegate MmsDataAccessError WriteAccessHandler (DataAttribute dataAttr, MmsValue value, + public delegate MmsDataAccessError WriteAccessHandler(DataAttribute dataAttr, MmsValue value, ClientConnection connection, object parameter); /// @@ -2230,7 +2264,8 @@ namespace IEC61850 /// /// Return type of ControlHandler and ControlWaitForExecutionHandler /// - public enum ControlHandlerResult { + public enum ControlHandlerResult + { /// /// check or operation failed /// @@ -2245,11 +2280,12 @@ namespace IEC61850 WAITING = 2 } - public delegate ControlHandlerResult ControlWaitForExecutionHandler (ControlAction action, object parameter, MmsValue ctlVal, bool test, bool synchroCheck); + public delegate ControlHandlerResult ControlWaitForExecutionHandler(ControlAction action, object parameter, MmsValue ctlVal, bool test, bool synchroCheck); - public delegate ControlHandlerResult ControlHandler (ControlAction action, object parameter, MmsValue ctlVal, bool test); + public delegate ControlHandlerResult ControlHandler(ControlAction action, object parameter, MmsValue ctlVal, bool test); - public enum CheckHandlerResult { + public enum CheckHandlerResult + { /// /// check passed /// @@ -2286,8 +2322,8 @@ namespace IEC61850 DATASET_WRITE, DATASET_GET_DIRECTORY } - - public delegate CheckHandlerResult CheckHandler (ControlAction action, object parameter, MmsValue ctlVal, bool test, bool interlockCheck); + + public delegate CheckHandlerResult CheckHandler(ControlAction action, object parameter, MmsValue ctlVal, bool test, bool interlockCheck); public static class SqliteLogStorage { @@ -2455,13 +2491,13 @@ namespace IEC61850 /// public class IedServer : IDisposable { - [DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr IedServer_createWithConfig(IntPtr modelRef, IntPtr tlsConfiguration, IntPtr serverConfiguratio); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void IedServer_setLocalIpAddress(IntPtr self, string localIpAddress); - [DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)] + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void IedServer_start(IntPtr self, int tcpPort); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] @@ -2611,6 +2647,29 @@ namespace IEC61850 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void IedServer_SVCBEventHandler(IntPtr svcb, int eventType, IntPtr parameter); + /// + /// set the authenticator for this server + /// This function sets a user specified authenticator that is used to identify and authenticate clients that + /// wants to connect.The authenticator is called on each connection attempt.Depending on the return value + /// connections are accepted. + /// + /// the instance of IedServer to operate on. + /// the user provided authenticator callback + /// user provided parameter that is passed to the authenticator + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void IedServer_setAuthenticator(IntPtr self, IedServer_AcseAuthenticator authenticator, IntPtr authenticatorParameter); + + /// + /// Callback function to authenticate a client + /// + /// user provided parameter - set when user registers the authenticator + /// the authentication parameters provided by the client + /// pointer where to store an application specific security token - can be ignored if not used. + /// ISO application reference (ap-title + ae-qualifier) + /// true if client connection is accepted, false otherwise + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate bool IedServer_AcseAuthenticator(IntPtr parameter, IntPtr authParameter, IntPtr securityToken, IntPtr appReference); + /// /// callback handler to control client read access to data attributes /// User provided callback function to control MMS client read access to IEC 61850 @@ -2697,13 +2756,13 @@ namespace IEC61850 public delegate bool IedServer_ListObjectsAccessHandler(IntPtr parameter, ClientConnection connection, ACSIClass acsiClass, LogicalDevice ld, LogicalNode ln, string objectName, string subObjectName, FunctionalConstraint fc); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int InternalControlPerformCheckHandler (IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool interlockCheck); + private delegate int InternalControlPerformCheckHandler(IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool interlockCheck); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int InternalControlWaitForExecutionHandler (IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool synchoCheck); + private delegate int InternalControlWaitForExecutionHandler(IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test, [MarshalAs(UnmanagedType.I1)] bool synchoCheck); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int InternalControlHandler (IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test); + private delegate int InternalControlHandler(IntPtr action, IntPtr parameter, IntPtr ctlVal, [MarshalAs(UnmanagedType.I1)] bool test); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void InternalSelectStateChangedHandler(IntPtr action, IntPtr parameter, [MarshalAs(UnmanagedType.I1)] bool isSelected, int reason); @@ -2715,7 +2774,7 @@ namespace IEC61850 static extern void IedServer_setPerformCheckHandler(IntPtr self, IntPtr node, InternalControlPerformCheckHandler handler, IntPtr parameter); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void IedServer_setControlHandler (IntPtr self, IntPtr node, InternalControlHandler handler, IntPtr parameter); + static extern void IedServer_setControlHandler(IntPtr self, IntPtr node, InternalControlHandler handler, IntPtr parameter); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void IedServer_setSelectStateChangedHandler(IntPtr self, IntPtr node, InternalSelectStateChangedHandler handler, IntPtr parameter); @@ -2724,7 +2783,7 @@ namespace IEC61850 static extern void IedServer_setWriteAccessPolicy(IntPtr self, FunctionalConstraint fc, AccessPolicy policy); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int InternalWriteAccessHandler (IntPtr dataAttribute, IntPtr value, IntPtr connection, IntPtr parameter); + private delegate int InternalWriteAccessHandler(IntPtr dataAttribute, IntPtr value, IntPtr connection, IntPtr parameter); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void IedServer_handleWriteAccess(IntPtr self, IntPtr dataAttribute, @@ -2750,7 +2809,7 @@ namespace IEC61850 } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void InternalConnectionHandler (IntPtr iedServer, IntPtr clientConnection, [MarshalAs(UnmanagedType.I1)] bool connected, IntPtr parameter); + private delegate void InternalConnectionHandler(IntPtr iedServer, IntPtr clientConnection, [MarshalAs(UnmanagedType.I1)] bool connected, IntPtr parameter); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void IedServer_setConnectionIndicationHandler(IntPtr self, InternalConnectionHandler handler, IntPtr parameter); @@ -2795,7 +2854,8 @@ namespace IEC61850 // hold references to managed LogStorage instances to avoid problems with GC private Dictionary logStorages = new Dictionary(); - internal class ControlHandlerInfo { + internal class ControlHandlerInfo + { public DataObject controlObject = null; public GCHandle handle; @@ -2814,58 +2874,59 @@ namespace IEC61850 public ControlHandlerInfo(DataObject controlObject) { this.controlObject = controlObject; - this.handle = GCHandle.Alloc(this); + handle = GCHandle.Alloc(this); } ~ControlHandlerInfo() { - this.handle.Free(); + handle.Free(); } } - private Dictionary controlHandlers = new Dictionary (); + private Dictionary controlHandlers = new Dictionary(); - int InternalControlHandlerImpl (IntPtr action, IntPtr parameter, IntPtr ctlVal, bool test) + int InternalControlHandlerImpl(IntPtr action, IntPtr parameter, IntPtr ctlVal, bool test) { - GCHandle handle = GCHandle.FromIntPtr (parameter); + GCHandle handle = GCHandle.FromIntPtr(parameter); ControlHandlerInfo info = (ControlHandlerInfo)handle.Target; - ControlAction controlAction = new ControlAction (action, info, this); + ControlAction controlAction = new ControlAction(action, info, this); if (info != null && info.controlHandler != null) - return (int)info.controlHandler (controlAction, info.controlHandlerParameter, new MmsValue (ctlVal), test); + return (int)info.controlHandler(controlAction, info.controlHandlerParameter, new MmsValue(ctlVal), test); else return (int)ControlHandlerResult.FAILED; } int InternalCheckHandlerImpl(IntPtr action, IntPtr parameter, IntPtr ctlVal, bool test, bool interlockCheck) { - GCHandle handle = GCHandle.FromIntPtr (parameter); + GCHandle handle = GCHandle.FromIntPtr(parameter); ControlHandlerInfo info = (ControlHandlerInfo)handle.Target; - if (info != null && info.checkHandler != null) + if (info != null && info.checkHandler != null) { - ControlAction controlAction = new ControlAction (action, info, this); + ControlAction controlAction = new ControlAction(action, info, this); - return (int)info.checkHandler (controlAction, info.checkHandlerParameter, new MmsValue (ctlVal), test, interlockCheck); - } else + return (int)info.checkHandler(controlAction, info.checkHandlerParameter, new MmsValue(ctlVal), test, interlockCheck); + } + else return (int)CheckHandlerResult.OBJECT_UNDEFINED; } - int InternalControlWaitForExecutionHandlerImpl (IntPtr action, IntPtr parameter, IntPtr ctlVal, bool test, bool synchoCheck) + int InternalControlWaitForExecutionHandlerImpl(IntPtr action, IntPtr parameter, IntPtr ctlVal, bool test, bool synchoCheck) { - GCHandle handle = GCHandle.FromIntPtr (parameter); + GCHandle handle = GCHandle.FromIntPtr(parameter); ControlHandlerInfo info = (ControlHandlerInfo)handle.Target; if (info != null && info.waitForExecHandler != null) { - ControlAction controlAction = new ControlAction (action, info, this); + ControlAction controlAction = new ControlAction(action, info, this); - return (int)info.waitForExecHandler (controlAction, info.waitForExecHandlerParameter, new MmsValue (ctlVal), test, synchoCheck); - } + return (int)info.waitForExecHandler(controlAction, info.waitForExecHandlerParameter, new MmsValue(ctlVal), test, synchoCheck); + } else return (int)ControlHandlerResult.FAILED; } @@ -2884,13 +2945,14 @@ namespace IEC61850 } } - private struct WriteAccessHandlerInfo { + private struct WriteAccessHandlerInfo + { public WriteAccessHandler handler; public InternalWriteAccessHandler internalHandler; public object parameter; public DataAttribute dataAttribute; - public WriteAccessHandlerInfo (WriteAccessHandler h, object p, DataAttribute da, InternalWriteAccessHandler internalHandler) + public WriteAccessHandlerInfo(WriteAccessHandler h, object p, DataAttribute da, InternalWriteAccessHandler internalHandler) { handler = h; parameter = p; @@ -2899,7 +2961,7 @@ namespace IEC61850 } } - int WriteAccessHandlerImpl (IntPtr dataAttribute, IntPtr value, IntPtr connection, IntPtr parameter) + int WriteAccessHandlerImpl(IntPtr dataAttribute, IntPtr value, IntPtr connection, IntPtr parameter) { WriteAccessHandlerInfo info; @@ -2915,7 +2977,7 @@ namespace IEC61850 } else { - return (int) MmsDataAccessError.OBJECT_ACCESS_DENIED; + return (int)MmsDataAccessError.OBJECT_ACCESS_DENIED; } } @@ -2938,7 +3000,7 @@ namespace IEC61850 { ClientConnection con = null; - this.clientConnections.TryGetValue(connection, out con); + clientConnections.TryGetValue(connection, out con); ModelNode ldModelNode = iedModel.GetModelNodeFromNodeRef(ld); ModelNode lnModelNode = iedModel.GetModelNodeFromNodeRef(ln); @@ -2994,13 +3056,13 @@ namespace IEC61850 } } - private bool InternalDataSetlHandlerImplementation (IntPtr parameter, IntPtr connection, int operation, string datasetRef) + private bool InternalDataSetlHandlerImplementation(IntPtr parameter, IntPtr connection, int operation, string datasetRef) { if (dataSetAccessHandler != null && connection != IntPtr.Zero) { ClientConnection con = null; - this.clientConnections.TryGetValue(connection, out con); + clientConnections.TryGetValue(connection, out con); return dataSetAccessHandler(dataSetAccessHandlerParameter, con, (DataSetOperation)operation, datasetRef); } @@ -3016,7 +3078,7 @@ namespace IEC61850 private IedServer_ActiveSettingGroupChangedHandler internalActiveSettingGroupChangedHandler = null; - public void SetActiveSettingGroupChangedHandler(ActiveSettingGroupChangedHandler handler,SettingGroupControlBlock settingGroupControlBlock, object parameter) + public void SetActiveSettingGroupChangedHandler(ActiveSettingGroupChangedHandler handler, SettingGroupControlBlock settingGroupControlBlock, object parameter) { activeSettingGroupChangedHandler = handler; activeSettingGroupChangedHandlerParameter = parameter; @@ -3040,7 +3102,7 @@ namespace IEC61850 { ClientConnection con = null; - this.clientConnections.TryGetValue(connection, out con); + clientConnections.TryGetValue(connection, out con); return activeSettingGroupChangedHandler(activeSettingGroupChangedHandlerParameter, new SettingGroupControlBlock(sgcb), newActSg, con); } @@ -3075,7 +3137,7 @@ namespace IEC61850 { ClientConnection con = null; - this.clientConnections.TryGetValue(connection, out con); + clientConnections.TryGetValue(connection, out con); return editSettingGroupChangedHandler(editSettingGroupChangedHandlerParameter, new SettingGroupControlBlock(sgcb), newEditSg, con); } @@ -3100,7 +3162,7 @@ namespace IEC61850 { internalEditSettingGroupConfirmationHandler = new IedServer_EditSettingGroupConfirmationHandler(InternalEditSettingGroupConfirmationImplementation); - IedServer_setEditSettingGroupConfirmationHandler(self, settingGroupControlBlock.self, internalEditSettingGroupConfirmationHandler, IntPtr.Zero); + IedServer_setEditSettingGroupConfirmationHandler(self, settingGroupControlBlock.self, internalEditSettingGroupConfirmationHandler, IntPtr.Zero); } } @@ -3127,12 +3189,12 @@ namespace IEC61850 public SVCHandlerInfo(SVControlBlock sampledValuesControlBlock) { this.sampledValuesControlBlock = sampledValuesControlBlock; - this.handle = GCHandle.Alloc(this); + handle = GCHandle.Alloc(this); } ~SVCHandlerInfo() { - this.handle.Free(); + handle.Free(); } } @@ -3166,7 +3228,6 @@ namespace IEC61850 IedServer_setSVCBHandler(self, sampledValuesControlBlock.Self, internalSVCBEventHandler, GCHandle.ToIntPtr(info.handle)); } - private void InternalSVCBEventHandlerImplementation(IntPtr svcb, int eventType, IntPtr parameter) { GCHandle handle = GCHandle.FromIntPtr(parameter); @@ -3177,6 +3238,38 @@ namespace IEC61850 info.sVCBEventHandler(info.sampledValuesControlBlock, (SMVEvent)eventType, info.svcHandlerParameter); } + //TODO -> Add appReference + public delegate bool AcseAuthenticatorHandler(object parameter, AcseAuthenticationParameter authParameter, object securityToken, IsoApplicationReference isoApplicationReference); + + private AcseAuthenticatorHandler acseAuthenticatorHandler = null; + private object acseAuthenticatorHandlerParameter = null; + private IedServer_AcseAuthenticator iedServer_AcseAuthenticator = null; + + public void SetAuthenticator(AcseAuthenticatorHandler acseAuthenticatorHandler, object acseAuthenticatorHandlerParameter) + { + this.acseAuthenticatorHandler = acseAuthenticatorHandler; + this.acseAuthenticatorHandlerParameter = acseAuthenticatorHandlerParameter; + + if (iedServer_AcseAuthenticator == null) + { + iedServer_AcseAuthenticator = new IedServer_AcseAuthenticator(InternalAcseAuthenticator); + IedServer_setAuthenticator(self, iedServer_AcseAuthenticator, IntPtr.Zero); + } + } + + private bool InternalAcseAuthenticator(IntPtr parameter, IntPtr authParameter, IntPtr securityToken, IntPtr appReference) + { + if (acseAuthenticatorHandler != null && authParameter != IntPtr.Zero && appReference != IntPtr.Zero) + { + AcseAuthenticationParameter acseAuthenticationParameter = new AcseAuthenticationParameter(authParameter); + IsoApplicationReference isoApplicationReference = new IsoApplicationReference(appReference); + GCHandle token = GCHandle.FromIntPtr(securityToken); + return acseAuthenticatorHandler(acseAuthenticatorHandlerParameter, acseAuthenticationParameter, token, isoApplicationReference); + } + + return false; + } + public delegate MmsDataAccessError ReadAccessHandler(LogicalDevice ld, LogicalNode ln, DataObject dataObject, FunctionalConstraint fc, ClientConnection connection, object parameter); private ReadAccessHandler readAccessHandler = null; @@ -3192,7 +3285,7 @@ namespace IEC61850 if (internalReadAccessHandler == null) { - internalReadAccessHandler = new IedServer_ReadAccessHandler (InternalReadHandlerImplementation); + internalReadAccessHandler = new IedServer_ReadAccessHandler(InternalReadHandlerImplementation); IedServer_setReadAccessHandler(self, internalReadAccessHandler, IntPtr.Zero); } @@ -3204,14 +3297,14 @@ namespace IEC61850 { ClientConnection con = null; - this.clientConnections.TryGetValue(connection, out con); + clientConnections.TryGetValue(connection, out con); ModelNode ldModelNode = iedModel.GetModelNodeFromNodeRef(ld); ModelNode lnModelNode = iedModel.GetModelNodeFromNodeRef(ln); ModelNode doModelNode = null; - if(dataObject != IntPtr.Zero) - doModelNode = iedModel.GetModelNodeFromNodeRef(dataObject); + if (dataObject != IntPtr.Zero) + doModelNode = iedModel.GetModelNodeFromNodeRef(dataObject); return readAccessHandler(ldModelNode as LogicalDevice, lnModelNode as LogicalNode, doModelNode as DataObject, (FunctionalConstraint)fc, con, readAccessHandlerParameter); } @@ -3227,7 +3320,7 @@ namespace IEC61850 DIRECTORY_CAT_LOG_LIST } - public delegate bool DirectoryAccessHandler(object parameter, ClientConnection connection, IedServer_DirectoryCategory category,LogicalDevice ld); + public delegate bool DirectoryAccessHandler(object parameter, ClientConnection connection, IedServer_DirectoryCategory category, LogicalDevice ld); private DirectoryAccessHandler directoryAccessHandler = null; @@ -3254,11 +3347,11 @@ namespace IEC61850 { ClientConnection con = null; - this.clientConnections.TryGetValue(connection, out con); + clientConnections.TryGetValue(connection, out con); ModelNode ldModelNode = null; - if(logicalDevice != IntPtr.Zero) + if (logicalDevice != IntPtr.Zero) ldModelNode = iedModel.GetModelNodeFromNodeRef(logicalDevice); return directoryAccessHandler(directoryAccessHandlerParameter, con, (IedServer_DirectoryCategory)category, ldModelNode as LogicalDevice); @@ -3268,33 +3361,37 @@ namespace IEC61850 } - private Dictionary writeAccessHandlers = new Dictionary (); + private Dictionary writeAccessHandlers = new Dictionary(); - private void ConnectionIndicationHandlerImpl (IntPtr iedServer, IntPtr clientConnection, bool connected, IntPtr parameter) + private void ConnectionIndicationHandlerImpl(IntPtr iedServer, IntPtr clientConnection, bool connected, IntPtr parameter) { - if (connected == false) { + if (connected == false) + { ClientConnection con = null; - clientConnections.TryGetValue (clientConnection, out con); + clientConnections.TryGetValue(clientConnection, out con); + + if (con != null) + { - if (con != null) { - if (connectionHandler != null) - connectionHandler (this, con, false, connectionHandlerParameter); + connectionHandler(this, con, false, connectionHandlerParameter); - clientConnections.Remove (clientConnection); + clientConnections.Remove(clientConnection); } - } else { - ClientConnection con = new ClientConnection (clientConnection); + } + else + { + ClientConnection con = new ClientConnection(clientConnection); - clientConnections.Add (clientConnection, con); + clientConnections.Add(clientConnection, con); if (connectionHandler != null) - connectionHandler (this, con, true, connectionHandlerParameter); + connectionHandler(this, con, true, connectionHandlerParameter); } } - internal Dictionary clientConnections = new Dictionary (); + internal Dictionary clientConnections = new Dictionary(); /* store IedModel instance to prevent garbage collector */ private IedModel iedModel = null; @@ -3311,13 +3408,13 @@ namespace IEC61850 if (config != null) nativeConfig = config.self; - self = IedServer_createWithConfig (iedModel.self, IntPtr.Zero, nativeConfig); + self = IedServer_createWithConfig(iedModel.self, IntPtr.Zero, nativeConfig); } public IedServer(IedModel iedModel, TLSConfiguration tlsConfig, IedServerConfig config = null) { this.iedModel = iedModel; - this.tlsConfiguration = tlsConfig; + tlsConfiguration = tlsConfig; IntPtr nativeConfig = IntPtr.Zero; IntPtr nativeTLSConfig = IntPtr.Zero; @@ -3326,9 +3423,9 @@ namespace IEC61850 nativeConfig = config.self; if (tlsConfig != null) - nativeTLSConfig = tlsConfig.GetNativeInstance (); + nativeTLSConfig = tlsConfig.GetNativeInstance(); - self = IedServer_createWithConfig (iedModel.self, nativeTLSConfig, nativeConfig); + self = IedServer_createWithConfig(iedModel.self, nativeTLSConfig, nativeConfig); } private InternalConnectionHandler internalConnectionHandler = null; @@ -3339,7 +3436,7 @@ namespace IEC61850 /// Local IP address. public void SetLocalIpAddress(string localIpAddress) { - IedServer_setLocalIpAddress (self, localIpAddress); + IedServer_setLocalIpAddress(self, localIpAddress); } /// @@ -3349,8 +3446,8 @@ namespace IEC61850 /// TCP port to use public void Start(string localIpAddress, int tcpPort) { - SetLocalIpAddress (localIpAddress); - Start (tcpPort); + SetLocalIpAddress(localIpAddress); + Start(tcpPort); } /// Start MMS server @@ -3358,15 +3455,15 @@ namespace IEC61850 public void Start(int tcpPort) { if (internalConnectionHandler == null) - internalConnectionHandler = new InternalConnectionHandler (ConnectionIndicationHandlerImpl); + internalConnectionHandler = new InternalConnectionHandler(ConnectionIndicationHandlerImpl); - IedServer_setConnectionIndicationHandler (self, internalConnectionHandler, IntPtr.Zero); + IedServer_setConnectionIndicationHandler(self, internalConnectionHandler, IntPtr.Zero); IedServer_start(self, tcpPort); } /// Start MMS server - public void Start () + public void Start() { Start(-1); } @@ -3406,8 +3503,8 @@ namespace IEC61850 IedServer_destroy(self); self = IntPtr.Zero; internalConnectionHandler = null; - this.iedModel = null; - this.tlsConfiguration = null; + iedModel = null; + tlsConfiguration = null; } } } @@ -3450,51 +3547,52 @@ namespace IEC61850 { ControlHandlerInfo info; - controlHandlers.TryGetValue (controlObject, out info); + controlHandlers.TryGetValue(controlObject, out info); - if (info == null) { - info = new ControlHandlerInfo (controlObject); - controlHandlers.Add (controlObject, info); + if (info == null) + { + info = new ControlHandlerInfo(controlObject); + controlHandlers.Add(controlObject, info); } return info; } - public void SetControlHandler (DataObject controlObject, ControlHandler handler, object parameter) + public void SetControlHandler(DataObject controlObject, ControlHandler handler, object parameter) { - ControlHandlerInfo info = GetControlHandlerInfo (controlObject); + ControlHandlerInfo info = GetControlHandlerInfo(controlObject); info.controlHandler = handler; info.controlHandlerParameter = parameter; if (internalControlHandlerRef == null) - internalControlHandlerRef = new InternalControlHandler (InternalControlHandlerImpl); + internalControlHandlerRef = new InternalControlHandler(InternalControlHandlerImpl); IedServer_setControlHandler(self, controlObject.self, internalControlHandlerRef, GCHandle.ToIntPtr(info.handle)); } - public void SetCheckHandler (DataObject controlObject, CheckHandler handler, object parameter) + public void SetCheckHandler(DataObject controlObject, CheckHandler handler, object parameter) { - ControlHandlerInfo info = GetControlHandlerInfo (controlObject); + ControlHandlerInfo info = GetControlHandlerInfo(controlObject); info.checkHandler = handler; info.checkHandlerParameter = parameter; if (internalControlPerformCheckHandlerRef == null) - internalControlPerformCheckHandlerRef = new InternalControlPerformCheckHandler (InternalCheckHandlerImpl); + internalControlPerformCheckHandlerRef = new InternalControlPerformCheckHandler(InternalCheckHandlerImpl); IedServer_setPerformCheckHandler(self, controlObject.self, internalControlPerformCheckHandlerRef, GCHandle.ToIntPtr(info.handle)); } - public void SetWaitForExecutionHandler (DataObject controlObject, ControlWaitForExecutionHandler handler, object parameter) + public void SetWaitForExecutionHandler(DataObject controlObject, ControlWaitForExecutionHandler handler, object parameter) { - ControlHandlerInfo info = GetControlHandlerInfo (controlObject); + ControlHandlerInfo info = GetControlHandlerInfo(controlObject); info.waitForExecHandler = handler; info.waitForExecHandlerParameter = parameter; if (internalControlWaitForExecutionHandlerRef == null) - internalControlWaitForExecutionHandlerRef = new InternalControlWaitForExecutionHandler (InternalControlWaitForExecutionHandlerImpl); + internalControlWaitForExecutionHandlerRef = new InternalControlWaitForExecutionHandler(InternalControlWaitForExecutionHandlerImpl); IedServer_setWaitForExecutionHandler(self, controlObject.self, internalControlWaitForExecutionHandlerRef, GCHandle.ToIntPtr(info.handle)); } @@ -3534,13 +3632,13 @@ namespace IEC61850 /// the data attribute to monitor /// the callback function that is invoked if a client tries to write to the monitored data attribute. /// a user provided parameter that is passed to the WriteAccessHandler when called. - public void HandleWriteAccess (DataAttribute dataAttr, WriteAccessHandler handler, object parameter) + public void HandleWriteAccess(DataAttribute dataAttr, WriteAccessHandler handler, object parameter) { InternalWriteAccessHandler internalHandler = new InternalWriteAccessHandler(WriteAccessHandlerImpl); - - writeAccessHandlers.Add (dataAttr.self, new WriteAccessHandlerInfo(handler, parameter, dataAttr, internalHandler)); - IedServer_handleWriteAccess (self, dataAttr.self, internalHandler, IntPtr.Zero); + writeAccessHandlers.Add(dataAttr.self, new WriteAccessHandlerInfo(handler, parameter, dataAttr, internalHandler)); + + IedServer_handleWriteAccess(self, dataAttr.self, internalHandler, IntPtr.Zero); } private void AddHandlerInfoForDataAttributeRecursive(DataAttribute da, WriteAccessHandler handler, object parameter, InternalWriteAccessHandler internalHandler) @@ -3624,7 +3722,7 @@ namespace IEC61850 /// The new default access policy public void SetWriteAccessPolicy(FunctionalConstraint fc, AccessPolicy policy) { - IedServer_setWriteAccessPolicy (self, fc, policy); + IedServer_setWriteAccessPolicy(self, fc, policy); } /// @@ -3658,7 +3756,7 @@ namespace IEC61850 public void UpdateAttributeValue(DataAttribute dataAttr, MmsValue value) { - IedServer_updateAttributeValue (self, dataAttr.self, value.valueReference); + IedServer_updateAttributeValue(self, dataAttr.self, value.valueReference); } public void UpdateBooleanAttributeValue(DataAttribute dataAttr, bool value) @@ -3678,7 +3776,7 @@ namespace IEC61850 public void UpdateInt64AttributeValue(DataAttribute dataAttr, Int64 value) { - IedServer_updateInt64AttributeValue (self, dataAttr.self, value); + IedServer_updateInt64AttributeValue(self, dataAttr.self, value); } public void UpdateVisibleStringAttributeValue(DataAttribute dataAttr, string value) @@ -3699,7 +3797,7 @@ namespace IEC61850 public void UpdateTimestampAttributeValue(DataAttribute dataAttr, Timestamp timestamp) { - IedServer_updateTimestampAttributeValue (self, dataAttr.self, timestamp.self); + IedServer_updateTimestampAttributeValue(self, dataAttr.self, timestamp.self); } public void UpdateQuality(DataAttribute dataAttr, ushort value) @@ -3709,10 +3807,10 @@ namespace IEC61850 public MmsValue GetAttributeValue(DataAttribute dataAttr) { - IntPtr mmsValuePtr = IedServer_getAttributeValue (self, dataAttr.self); + IntPtr mmsValuePtr = IedServer_getAttributeValue(self, dataAttr.self); if (mmsValuePtr != IntPtr.Zero) - return new MmsValue (mmsValuePtr); + return new MmsValue(mmsValuePtr); else return null; } @@ -3829,7 +3927,7 @@ namespace IEC61850 { goCbEventHandler = handler; goCbEventHandlerParameter = parameter; - + if (internalGoCBEventHandler == null) { internalGoCBEventHandler = new InternalGoCBEventHandler(InternalGoCBEventHandlerImplementation); @@ -3854,7 +3952,7 @@ namespace IEC61850 if (connection != IntPtr.Zero) { - this.clientConnections.TryGetValue(connection, out con); + clientConnections.TryGetValue(connection, out con); } ReportControlBlock reportControlBlock = null; diff --git a/dotnet/IEC61850forCSharp/IedServerConfig.cs b/dotnet/IEC61850forCSharp/IedServerConfig.cs index 0f17815a..60b68a64 100644 --- a/dotnet/IEC61850forCSharp/IedServerConfig.cs +++ b/dotnet/IEC61850forCSharp/IedServerConfig.cs @@ -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 { diff --git a/dotnet/IEC61850forCSharp/IsoConnectionParameters.cs b/dotnet/IEC61850forCSharp/IsoConnectionParameters.cs index 5a1cfbe1..5a8685cb 100644 --- a/dotnet/IEC61850forCSharp/IsoConnectionParameters.cs +++ b/dotnet/IEC61850forCSharp/IsoConnectionParameters.cs @@ -1,7 +1,7 @@ /* * IsoConnectionParameters.cs * - * Copyright 2014 Michael Zillgith + * Copyright 2014-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -26,38 +26,39 @@ using System.Runtime.InteropServices; namespace IEC61850 { - namespace Client - { + namespace Client + { - public enum AcseAuthenticationMechanism { + public enum AcseAuthenticationMechanism + { /** don't use authentication */ - ACSE_AUTH_NONE = 0, + ACSE_AUTH_NONE = 0, /** use password authentication */ - ACSE_AUTH_PASSWORD = 1 - } + ACSE_AUTH_PASSWORD = 1 + } /// /// Connection parameters associated with the ISO protocol layers (transport, session, presentation, ACSE) /// public class IsoConnectionParameters - { + { [StructLayout(LayoutKind.Sequential)] private struct NativeTSelector { public byte size; - [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public byte[] value; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] value; } - [StructLayout(LayoutKind.Sequential)] - private struct NativeSSelector - { - public byte size; + [StructLayout(LayoutKind.Sequential)] + private struct NativeSSelector + { + public byte size; - [MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] public byte[] value; - } + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] value; + } [StructLayout(LayoutKind.Sequential)] private struct NativePSelector @@ -68,49 +69,49 @@ namespace IEC61850 } [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void IsoConnectionParameters_destroy(IntPtr self); + private static extern void IsoConnectionParameters_destroy(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void IsoConnectionParameters_setRemoteApTitle(IntPtr self, string apTitle, int aeQualifier); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void IsoConnectionParameters_setRemoteApTitle(IntPtr self, string apTitle, int aeQualifier); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void IsoConnectionParameters_setRemoteAddresses(IntPtr self, NativePSelector pSelector, NativeSSelector sSelector, NativeTSelector tSelector); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void IsoConnectionParameters_setRemoteAddresses(IntPtr self, NativePSelector pSelector, NativeSSelector sSelector, NativeTSelector tSelector); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void IsoConnectionParameters_setLocalApTitle(IntPtr self, string apTitle, int aeQualifier); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void IsoConnectionParameters_setLocalApTitle(IntPtr self, string apTitle, int aeQualifier); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void IsoConnectionParameters_setLocalAddresses(IntPtr self, NativePSelector pSelector, NativeSSelector sSelector, NativeTSelector tSelector); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void IsoConnectionParameters_setLocalAddresses(IntPtr self, NativePSelector pSelector, NativeSSelector sSelector, NativeTSelector tSelector); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void IsoConnectionParameters_setAcseAuthenticationParameter(IntPtr self, IntPtr acseAuthParameter); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void IsoConnectionParameters_setAcseAuthenticationParameter(IntPtr self, IntPtr acseAuthParameter); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr AcseAuthenticationParameter_create(); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr AcseAuthenticationParameter_create(); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void AcseAuthenticationParameter_destroy(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void AcseAuthenticationParameter_destroy(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void AcseAuthenticationParameter_setAuthMechanism(IntPtr self, int mechanism); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void AcseAuthenticationParameter_setAuthMechanism(IntPtr self, int mechanism); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void AcseAuthenticationParameter_setPassword(IntPtr self, string password); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void AcseAuthenticationParameter_setPassword(IntPtr self, string password); - private IntPtr self; + private IntPtr self; - private IntPtr authParameter = IntPtr.Zero; + private IntPtr authParameter = IntPtr.Zero; - internal IsoConnectionParameters (IntPtr self) - { - this.self = self; - } + internal IsoConnectionParameters(IntPtr self) + { + this.self = self; + } - ~IsoConnectionParameters () - { - if (authParameter != IntPtr.Zero) - AcseAuthenticationParameter_destroy(authParameter); - } + ~IsoConnectionParameters() + { + if (authParameter != IntPtr.Zero) + AcseAuthenticationParameter_destroy(authParameter); + } /// /// Sets the remote ap title related parameters @@ -122,9 +123,9 @@ namespace IEC61850 /// remote AE qualifier. /// public void SetRemoteApTitle(string apTitle, int aeQualifier) - { - IsoConnectionParameters_setRemoteApTitle(self, apTitle, aeQualifier); - } + { + IsoConnectionParameters_setRemoteApTitle(self, apTitle, aeQualifier); + } /// /// Sets the remote addresses for ISO layers (transport, session, presentation) @@ -138,27 +139,27 @@ namespace IEC61850 /// /// ISO COTP transport layer address /// - 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++) + for (int i = 0; i < tSelector.Length; i++) nativeTSelector.value[i] = tSelector[i]; - if (sSelector.Length > 16) - throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded"); + if (sSelector.Length > 16) + throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded"); - NativeSSelector nativeSSelector; - nativeSSelector.size = (byte) sSelector.Length; - nativeSSelector.value = new byte[16]; + NativeSSelector nativeSSelector; + nativeSSelector.size = (byte)sSelector.Length; + nativeSSelector.value = new byte[16]; - for (int i = 0; i < sSelector.Length; i++) - nativeSSelector.value [i] = sSelector [i]; + for (int i = 0; i < sSelector.Length; i++) + nativeSSelector.value[i] = sSelector[i]; if (pSelector.Length > 16) throw new ArgumentOutOfRangeException("pSelector", "maximum size (16) exceeded"); @@ -171,7 +172,7 @@ namespace IEC61850 nativePSelector.value[i] = pSelector[i]; IsoConnectionParameters_setRemoteAddresses(self, nativePSelector, nativeSSelector, nativeTSelector); - } + } /// /// Sets the local ap title related parameters @@ -182,10 +183,10 @@ namespace IEC61850 /// /// local AE qualifier. /// - public void SetLocalApTitle (string apTitle, int aeQualifier) - { - IsoConnectionParameters_setLocalApTitle(self, apTitle, aeQualifier); - } + public void SetLocalApTitle(string apTitle, int aeQualifier) + { + IsoConnectionParameters_setLocalApTitle(self, apTitle, aeQualifier); + } /// /// Sets the local addresses for ISO layers (transport, session, presentation) @@ -199,27 +200,27 @@ namespace IEC61850 /// /// ISO COTP transport layer address /// - 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++) + for (int i = 0; i < tSelector.Length; i++) nativeTSelector.value[i] = tSelector[i]; - if (sSelector.Length > 16) - throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded"); + if (sSelector.Length > 16) + throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded"); - NativeSSelector nativeSSelector; - nativeSSelector.size = (byte) sSelector.Length; - nativeSSelector.value = new byte[16]; + NativeSSelector nativeSSelector; + nativeSSelector.size = (byte)sSelector.Length; + nativeSSelector.value = new byte[16]; - for (int i = 0; i < sSelector.Length; i++) - nativeSSelector.value [i] = sSelector [i]; + for (int i = 0; i < sSelector.Length; i++) + nativeSSelector.value[i] = sSelector[i]; if (pSelector.Length > 16) throw new ArgumentOutOfRangeException("pSelector", "maximum size (16) exceeded"); @@ -232,7 +233,7 @@ namespace IEC61850 nativePSelector.value[i] = pSelector[i]; IsoConnectionParameters_setLocalAddresses(self, nativePSelector, nativeSSelector, nativeTSelector); - } + } /// /// Instruct ACSE layer to use password authentication. @@ -240,19 +241,20 @@ namespace IEC61850 /// /// Password that will be used to authenticate the client /// - public void UsePasswordAuthentication (string password) - { - if (authParameter == IntPtr.Zero) { - authParameter = AcseAuthenticationParameter_create (); - AcseAuthenticationParameter_setAuthMechanism (authParameter, (int)AcseAuthenticationMechanism.ACSE_AUTH_PASSWORD); - AcseAuthenticationParameter_setPassword (authParameter, password); - IsoConnectionParameters_setAcseAuthenticationParameter(self, authParameter); - } - else - throw new IedConnectionException("Authentication parameter already set"); - } - } - - } + public void UsePasswordAuthentication(string password) + { + if (authParameter == IntPtr.Zero) + { + authParameter = AcseAuthenticationParameter_create(); + AcseAuthenticationParameter_setAuthMechanism(authParameter, (int)AcseAuthenticationMechanism.ACSE_AUTH_PASSWORD); + AcseAuthenticationParameter_setPassword(authParameter, password); + IsoConnectionParameters_setAcseAuthenticationParameter(self, authParameter); + } + else + throw new IedConnectionException("Authentication parameter already set"); + } + } + + } } diff --git a/dotnet/IEC61850forCSharp/MmsValue.cs b/dotnet/IEC61850forCSharp/MmsValue.cs index 97020ab1..c140b37a 100644 --- a/dotnet/IEC61850forCSharp/MmsValue.cs +++ b/dotnet/IEC61850forCSharp/MmsValue.cs @@ -1,7 +1,7 @@ /* * MmsValue.cs * - * Copyright 2014 Michael Zillgith + * Copyright 2014-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -21,49 +21,46 @@ * 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 -{ - namespace Common - { +{ + namespace Common + { /// /// This class is used to hold MMS data values of different types. /// - public class MmsValue : IEnumerable, IDisposable - { - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_toString (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern float MmsValue_toFloat (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void MmsValue_setFloat (IntPtr self, float value); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern double MmsValue_toDouble (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); + public class MmsValue : IEnumerable, IDisposable + { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_toString(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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void MmsValue_setBitStringFromInteger(IntPtr self, UInt32 intValue); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern float MmsValue_toFloat(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void MmsValue_setFloat(IntPtr self, float value); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern double MmsValue_toDouble(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void MmsValue_setBitStringFromInteger(IntPtr self, UInt32 intValue); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 MmsValue_getBitStringAsIntegerBigEndian(IntPtr self); @@ -71,108 +68,108 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void MmsValue_setBitStringFromIntegerBigEndian(IntPtr self, UInt32 intValue); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern int MmsValue_getBitStringSize(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void MmsValue_setBitStringBit(IntPtr self, int bitPos, [MarshalAs(UnmanagedType.I1)] bool value); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - static extern bool MmsValue_getBitStringBit(IntPtr self, int bitPos); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 MmsValue_toUint32 (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern int MmsValue_getType (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void MmsValue_delete (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_getElement (IntPtr complexValue, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern int MmsValue_getArraySize (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern ulong MmsValue_getUtcTimeInMs (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void MmsValue_setUtcTimeQuality (IntPtr self, byte timeQuality); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 MmsValue_toUnixTimestamp (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newBoolean ([MarshalAs(UnmanagedType.I1)] bool value); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newFloat (float value); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newDouble (double value); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int MmsValue_getBitStringSize(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void MmsValue_setBitStringBit(IntPtr self, int bitPos, [MarshalAs(UnmanagedType.I1)] bool value); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool MmsValue_getBitStringBit(IntPtr self, int bitPos); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 MmsValue_toUint32(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int MmsValue_getType(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void MmsValue_delete(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_getElement(IntPtr complexValue, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int MmsValue_getArraySize(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern ulong MmsValue_getUtcTimeInMs(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newIntegerFromInt32 (Int32 integer); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void MmsValue_setUtcTimeQuality(IntPtr self, byte timeQuality); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 MmsValue_toUnixTimestamp(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_newBoolean([MarshalAs(UnmanagedType.I1)] bool value); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_newFloat(float value); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_newDouble(double value); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newBitString(int bitSize); + static extern IntPtr MmsValue_newUnsignedFromUint32(UInt32 integer); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newVisibleString(string value); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newVisibleStringWithSize(int size); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void MmsValue_setVisibleString(IntPtr self, string value); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_createArray(IntPtr elementType, int size); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_createEmptyArray(int size); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_createEmptyStructure(int size); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newOctetString(int size, int maxSize); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void MmsValue_setOctetString(IntPtr self, [Out] byte[] buf, int size); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt16 MmsValue_getOctetStringSize(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt16 MmsValue_getOctetStringMaxSize(IntPtr self); + static extern IntPtr MmsValue_newIntegerFromInt64(Int64 integer); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_newBitString(int bitSize); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_newVisibleString(string value); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_newVisibleStringWithSize(int size); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void MmsValue_setVisibleString(IntPtr self, string value); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_createArray(IntPtr elementType, int size); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_createEmptyArray(int size); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_createEmptyStructure(int size); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_newOctetString(int size, int maxSize); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void MmsValue_setOctetString(IntPtr self, [Out] byte[] buf, int size); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt16 MmsValue_getOctetStringSize(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt16 MmsValue_getOctetStringMaxSize(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern byte MmsValue_getOctetStringOctet(IntPtr self, int pos); @@ -180,33 +177,33 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void MmsValue_setOctetStringOctet(IntPtr self, int pos, byte value); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_getOctetStringBuffer(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_getOctetStringBuffer(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] - static extern bool MmsValue_equals(IntPtr self, IntPtr otherValue); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newBinaryTime ([MarshalAs(UnmanagedType.I1)] bool timeOfDay); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void MmsValue_setBinaryTime (IntPtr self, UInt64 timestamp); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern ulong MmsValue_getBinaryTimeAsUtcMs (IntPtr self); - - [DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_newUtcTimeByMsTime (UInt64 timestamp); + static extern bool MmsValue_equals(IntPtr self, IntPtr otherValue); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_newBinaryTime([MarshalAs(UnmanagedType.I1)] bool timeOfDay); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void MmsValue_setBinaryTime(IntPtr self, UInt64 timestamp); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern ulong MmsValue_getBinaryTimeAsUtcMs(IntPtr self); - [DllImport("iec61850", CallingConvention=CallingConvention.Cdecl)] - static extern int MmsValue_getDataAccessError(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr MmsValue_newUtcTimeByMsTime(UInt64 timestamp); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void MmsValue_setElement(IntPtr complexValue, int index, IntPtr elementValue); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int MmsValue_getDataAccessError(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void MmsValue_setElement(IntPtr complexValue, int index, IntPtr elementValue); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsVariableSpecification_getChildValue(IntPtr self, IntPtr value, string childId); + static extern IntPtr MmsVariableSpecification_getChildValue(IntPtr self, IntPtr value, string childId); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern int MmsValue_encodeMmsData(IntPtr self, byte[] buffer, int bufPos, bool encode); @@ -215,267 +212,272 @@ namespace IEC61850 static extern int MmsValue_decodeMmsData(IntPtr self, int bufPos, int bufferLength, IntPtr endBufPo); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr MmsValue_clone(IntPtr self); - - internal IntPtr valueReference; /* reference to native MmsValue instance */ - - private bool responsableForDeletion = false; /* if .NET wrapper is responsable for the deletion of the native MmsValue instance */ - - internal MmsValue (IntPtr value) - { - valueReference = value; - this.responsableForDeletion = false; - } + static extern IntPtr MmsValue_clone(IntPtr self); + + internal IntPtr valueReference; /* reference to native MmsValue instance */ + + private bool responsableForDeletion = false; /* if .NET wrapper is responsable for the deletion of the native MmsValue instance */ + + internal MmsValue(IntPtr value) + { + valueReference = value; + 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) - { - valueReference = value; - this.responsableForDeletion = responsableForDeletion; - } - - public MmsValue (bool value) - { - valueReference = MmsValue_newBoolean (value); - } - - public MmsValue (float value) - { - valueReference = MmsValue_newFloat (value); - } - - public MmsValue (double value) - { - valueReference = MmsValue_newDouble (value); - } - - public MmsValue (int value) - { - valueReference = MmsValue_newIntegerFromInt32 (value); - } + internal MmsValue(IntPtr value, bool responsableForDeletion) + { + valueReference = value; + this.responsableForDeletion = responsableForDeletion; + } + + public MmsValue(bool value) + { + valueReference = MmsValue_newBoolean(value); + } + + public MmsValue(float value) + { + valueReference = MmsValue_newFloat(value); + } + + public MmsValue(double value) + { + valueReference = MmsValue_newDouble(value); + } + + public MmsValue(int value) + { + valueReference = MmsValue_newIntegerFromInt32(value); + } - public MmsValue (UInt32 value) + public MmsValue(UInt32 value) { valueReference = MmsValue_newUnsignedFromUint32(value); - } - - public MmsValue (long value) - { - valueReference = MmsValue_newIntegerFromInt64 (value); - } - - /// - /// Create a new instance of type MMS_VISIBLE_STRING. - /// - /// Value. - public MmsValue (string value) + } + + public MmsValue(long value) + { + valueReference = MmsValue_newIntegerFromInt64(value); + } + + /// + /// Create a new instance of type MMS_VISIBLE_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(); + } + + /// + /// Create a new MmsValue instance of type MMS_BIT_STRING. + /// + /// + /// the new MmsValue instance + /// + /// + /// the size of the bit string in bits. + /// + public static MmsValue NewBitString(int bitSize) + { + IntPtr newValue = MmsValue_newBitString(bitSize); + + return new MmsValue(newValue, true); + } + + /// + /// Create a new MmsValue instance of type MMS_OCTET_STRING. + /// + /// + /// the new MmsValue instance + /// + /// + /// the maximum size of the octet string in bytes + /// + /// + /// the current size of the octet string in bytes (defaults to 0) + /// + public static MmsValue NewOctetString(int maxSize, int size = 0) + { + IntPtr newValue = MmsValue_newOctetString(size, maxSize); + + return new MmsValue(newValue, true); + } + + public MmsValue(byte[] octetString) + { + if (octetString.Length > 255) + throw new MmsValueException("octet string too long"); + + valueReference = MmsValue_newOctetString(octetString.Length, octetString.Length); + + setOctetString(octetString); + } + + /// + /// Create a new MmsValue instance of type MMS_ARRAY. Array elements have the fiven type + /// + /// the newly created array + /// array element type + /// number of array elements + public static MmsValue NewArray(MmsVariableSpecification elementType, int size) + { + if (size < 1) + throw new MmsValueException("array requires at least one element"); + + IntPtr newValue = MmsValue_createArray(elementType.self, size); + + return new MmsValue(newValue, true); + } + + /// + /// Create a new MmsValue instance of type MMS_ARRAY. Array elements are not initialized! + /// + /// the newly created array + /// number of array elements + public static MmsValue NewEmptyArray(int size) + { + if (size < 1) + throw new MmsValueException("array requires at least one element"); + + IntPtr newValue = MmsValue_createEmptyArray(size); + + return new MmsValue(newValue, true); + } + + /// + /// Create a new MmsValue instance of type MMS_STRUCTURE. Structure elements are not initialized! + /// + /// the newly created array + /// number of structure elements + public static MmsValue NewEmptyStructure(int size) + { + if (size < 1) + throw new MmsValueException("structure requires at least one element"); + + IntPtr newValue = MmsValue_createEmptyStructure(size); + + return new MmsValue(newValue, true); + } + + + /// + /// Create a new MmsValue instance of type MMS_BINARY_TIME + /// + /// the new MmsValue instance. + /// If set to true large 6 byte format. + public static MmsValue NewBinaryTime(bool largeFormat) + { + IntPtr newValue = MmsValue_newBinaryTime(largeFormat); + + return new MmsValue(newValue, true); + } + + /// + /// Sets the binary time. + /// + /// Timestamp. + public void SetBinaryTime(UInt64 timestamp) + { + MmsValue_setBinaryTime(valueReference, timestamp); + } + + /// + /// Gets the binary time value as UTC time in ms. + /// + /// + /// Return the value as milliseconds since epoch (1.1.1970 UTC). + /// The value has to be of type MMS_UTC_TIME. + /// + /// + /// The UTC time in ms. + /// + /// This exception is thrown if the value has the wrong type. + public ulong GetBinaryTimeAsUtcMs() + { + if (GetType() == MmsType.MMS_BINARY_TIME) + { + return MmsValue_getBinaryTimeAsUtcMs(valueReference); + } + else + throw new MmsValueException("Value is not a time type"); } - /// - /// Create a new MmsValue instance of type MMS_BIT_STRING. - /// - /// - /// the new MmsValue instance - /// - /// - /// the size of the bit string in bits. - /// - public static MmsValue NewBitString(int bitSize) - { - IntPtr newValue = MmsValue_newBitString(bitSize); - - return new MmsValue(newValue, true); - } - - /// - /// Create a new MmsValue instance of type MMS_OCTET_STRING. - /// - /// - /// the new MmsValue instance - /// - /// - /// the maximum size of the octet string in bytes - /// - /// - /// the current size of the octet string in bytes (defaults to 0) - /// - public static MmsValue NewOctetString (int maxSize, int size = 0) - { - IntPtr newValue = MmsValue_newOctetString(size, maxSize); - - return new MmsValue(newValue, true); - } - - public MmsValue(byte[] octetString) - { - if (octetString.Length > 255) - throw new MmsValueException ("octet string too long"); - - valueReference = MmsValue_newOctetString(octetString.Length, octetString.Length); - - this.setOctetString (octetString); - } - - /// - /// Create a new MmsValue instance of type MMS_ARRAY. Array elements have the fiven type - /// - /// the newly created array - /// array element type - /// number of array elements - public static MmsValue NewArray(MmsVariableSpecification elementType, int size) - { - if (size < 1) - throw new MmsValueException ("array requires at least one element"); - - IntPtr newValue = MmsValue_createArray (elementType.self, size); - - return new MmsValue (newValue, true); - } - - /// - /// Create a new MmsValue instance of type MMS_ARRAY. Array elements are not initialized! - /// - /// the newly created array - /// number of array elements - public static MmsValue NewEmptyArray(int size) - { - if (size < 1) - throw new MmsValueException ("array requires at least one element"); - - IntPtr newValue = MmsValue_createEmptyArray (size); - - return new MmsValue (newValue, true); - } - - /// - /// Create a new MmsValue instance of type MMS_STRUCTURE. Structure elements are not initialized! - /// - /// the newly created array - /// number of structure elements - public static MmsValue NewEmptyStructure(int size) - { - if (size < 1) - throw new MmsValueException ("structure requires at least one element"); - - IntPtr newValue = MmsValue_createEmptyStructure (size); - - return new MmsValue (newValue, true); - } - - - /// - /// Create a new MmsValue instance of type MMS_BINARY_TIME - /// - /// the new MmsValue instance. - /// If set to true large 6 byte format. - public static MmsValue NewBinaryTime(bool largeFormat) - { - IntPtr newValue = MmsValue_newBinaryTime (largeFormat); - - return new MmsValue (newValue, true); - } - - /// - /// Sets the binary time. - /// - /// Timestamp. - public void SetBinaryTime(UInt64 timestamp) { - MmsValue_setBinaryTime (this.valueReference, timestamp); - } - - /// - /// Gets the binary time value as UTC time in ms. - /// - /// - /// Return the value as milliseconds since epoch (1.1.1970 UTC). - /// The value has to be of type MMS_UTC_TIME. - /// - /// - /// The UTC time in ms. - /// - /// This exception is thrown if the value has the wrong type. - public ulong GetBinaryTimeAsUtcMs () - { - if (GetType () == MmsType.MMS_BINARY_TIME) { - return MmsValue_getBinaryTimeAsUtcMs (valueReference); - } else - throw new MmsValueException ("Value is not a time type"); - } - /// /// Create a new MmsValue instance of type MMS_UTC_TIME /// /// the new MmsValue instance. /// the time value as milliseconds since epoch (1.1.1970 UTC). - public static MmsValue NewUtcTime (UInt64 timestamp) + public static MmsValue NewUtcTime(UInt64 timestamp) { - IntPtr newValue = MmsValue_newUtcTimeByMsTime (timestamp); - - return new MmsValue (newValue, true); - } + IntPtr newValue = MmsValue_newUtcTimeByMsTime(timestamp); - /// + return new MmsValue(newValue, true); + } + + /// /// Create a new MmsValue instance of type MMS_VISIBLE_STRING - empty string with given maximum size /// /// The maximum size /// - public static MmsValue NewVisibleString(int size, bool responsibleForDeletion = false) - { - IntPtr newValue = MmsValue_newVisibleStringWithSize(size); - - return new MmsValue(newValue, responsibleForDeletion); - } - - /// + public static MmsValue NewVisibleString(int size, bool responsibleForDeletion = false) + { + IntPtr newValue = MmsValue_newVisibleStringWithSize(size); + + return new MmsValue(newValue, responsibleForDeletion); + } + + /// /// Set the value of an MmsValue instance of type MMS_VISIBLE_STRING /// /// the new string value - public void SetVisibleString(string value) - { - MmsValue_setVisibleString(valueReference, value); + public void SetVisibleString(string value) + { + MmsValue_setVisibleString(valueReference, value); + } + + /// + /// Gets the type of the value + /// + /// + /// The type. + /// + public new MmsType GetType() + { + return (MmsType)MmsValue_getType(valueReference); } - /// - /// Gets the type of the value - /// - /// - /// The type. - /// - public new MmsType GetType () - { - return (MmsType)MmsValue_getType (valueReference); - } - /// /// Gets the size of an array, structure, or bit string /// @@ -484,80 +486,87 @@ namespace IEC61850 /// Return the size of an array of structure (number of elements) /// The value has to be of type MMS_ARRAY, MMS_STRUCTURE, MMS_BIT_STRING ... /// - /// the number of elements (array/structure elements, octets, bits depending on type) + /// the number of elements (array/structure elements, octets, bits depending on type) + /// + /// This exception is thrown if the value has the wrong type. + public int Size() + { + 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) + { + return MmsValue_getOctetStringSize(valueReference); + } + else + throw new MmsValueException("Operation not supported for this type"); + } + + /// + /// Gets the maximum size of an octet string + /// + /// + /// The maximum size (in bytes) of the octet string + /// + public int MaxSize() + { + if (GetType() == MmsType.MMS_OCTET_STRING) + { + return MmsValue_getOctetStringMaxSize(valueReference); + } + else + throw new MmsValueException("Operation not supported for this type"); + } + + /// + /// Gets the octet string as byte array + /// + /// Instance has to be of type MMS_OCTET_STRING. + /// + /// + /// Byte array containing the bytes of the octet string. /// /// This exception is thrown if the value has the wrong type. - public int Size () - { - 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) { - return MmsValue_getOctetStringSize(valueReference); - } - else - throw new MmsValueException ("Operation not supported for this type"); - } - - /// - /// Gets the maximum size of an octet string - /// - /// - /// The maximum size (in bytes) of the octet string - /// - public int MaxSize () - { - if (GetType () == MmsType.MMS_OCTET_STRING) { - return MmsValue_getOctetStringMaxSize(valueReference); - } - else - throw new MmsValueException ("Operation not supported for this type"); - } - - /// - /// Gets the octet string as byte array - /// - /// Instance has to be of type MMS_OCTET_STRING. - /// - /// - /// Byte array containing the bytes of the octet string. - /// - /// This exception is thrown if the value has the wrong type. - public byte[] getOctetString () - { - if (GetType () == MmsType.MMS_OCTET_STRING) { - IntPtr buffer = MmsValue_getOctetStringBuffer(valueReference); - int bufferSize = this.Size(); - - byte[] octetString = new byte[bufferSize]; - - Marshal.Copy(buffer, octetString, 0, bufferSize); - - return octetString; - } - else - throw new MmsValueException ("Operation not supported for this type"); - } + public byte[] getOctetString() + { + if (GetType() == MmsType.MMS_OCTET_STRING) + { + IntPtr buffer = MmsValue_getOctetStringBuffer(valueReference); + int bufferSize = Size(); + + byte[] octetString = new byte[bufferSize]; + + Marshal.Copy(buffer, octetString, 0, bufferSize); + + return octetString; + } + else + throw new MmsValueException("Operation not supported for this type"); + } /// /// Sets the value of an octet string by a byte array /// /// Byte array containing the bytes of the octet string. /// This exception is thrown if the value has the wrong type or the byte array is too large. - public void setOctetString (byte[] octetString) - { - if (GetType () == MmsType.MMS_OCTET_STRING) { - - if (this.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"); - } + public void setOctetString(byte[] octetString) + { + if (GetType() == MmsType.MMS_OCTET_STRING) + { + + 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"); + } /// /// Gets the octet string octet. @@ -590,23 +599,27 @@ namespace IEC61850 /// /// This exception is thrown if the value has the wrong type. /// This exception is thrown if the index is out of range. - public MmsValue GetElement (int index) - { - MmsType type = GetType (); - - 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"); - } + public MmsValue GetElement(int index) + { + MmsType type = GetType(); + + 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"); + } /// /// Sets the element of an array or structure @@ -674,29 +687,31 @@ namespace IEC61850 /// The UTC time in seconds (UNIX time stamp). /// /// This exception is thrown if the value has the wrong type. - public UInt32 ToUnixTimestamp () - { - if (GetType () == MmsType.MMS_UTC_TIME) - return MmsValue_toUnixTimestamp (valueReference); - else - throw new MmsValueException ("Value is not a time type"); - } - - /// - /// Sets the timestamp value as UTC time in ms. - /// - /// + public UInt32 ToUnixTimestamp() + { + if (GetType() == MmsType.MMS_UTC_TIME) + return MmsValue_toUnixTimestamp(valueReference); + else + throw new MmsValueException("Value is not a time type"); + } + + /// + /// Sets the timestamp value as UTC time in ms. + /// + /// /// Sets the value as milliseconds since epoch (1.1.1970 UTC). /// The value has to be of type MMS_UTC_TIME. - /// + /// /// This exception is thrown if the value has the wrong type. - public void SetUtcTimeMs(ulong timeval) - { - if (GetType () == MmsType.MMS_UTC_TIME) { - MmsValue_setUtcTimeMs(valueReference, timeval); - } else - throw new MmsValueException ("Value is not a time type"); - } + public void SetUtcTimeMs(ulong timeval) + { + if (GetType() == MmsType.MMS_UTC_TIME) + { + MmsValue_setUtcTimeMs(valueReference, timeval); + } + else + throw new MmsValueException("Value is not a time type"); + } /// /// Gets the timestamp value as UTC time in ms. @@ -709,78 +724,80 @@ namespace IEC61850 /// The UTC time in ms. /// /// This exception is thrown if the value has the wrong type. - public ulong GetUtcTimeInMs () - { - if (GetType () == MmsType.MMS_UTC_TIME) { - return MmsValue_getUtcTimeInMs (valueReference); - } else - throw new MmsValueException ("Value is not a time type"); - } - - /// - /// Gets the timestamp value as UTC time in ms and the additional us part. - /// - /// - /// Return the value as milliseconds since epoch (1.1.1970 UTC) and the additional us part. - /// The value has to be of type MMS_UTC_TIME. - /// - /// - /// returns the usec part of the time value - /// - /// - /// The UTC time in ms. - /// - /// This exception is thrown if the value has the wrong type. - public ulong GetUtcTimeInMsWithUs(out int usec) - { - if (GetType() == MmsType.MMS_UTC_TIME) - { - uint uusec = 0; - var msVal = MmsValue_getUtcTimeInMsWithUs(valueReference, uusec); - usec = (int)uusec; - return msVal; - } - else - throw new MmsValueException("Value is not a time type"); - } - - /// - /// Gets quality flags of an UTC timestamp. - /// - /// - /// Meaning of the bits in the timeQuality byte: - /// bit 7 = leapSecondsKnown - /// bit 6 = clockFailure - /// bit 5 = clockNotSynchronized - /// bit 0-4 = subsecond time accuracy (number of significant bits of subsecond time) - /// - /// The UTC time quality. - public byte GetUtcTimeQuality() - { - if (GetType() == MmsType.MMS_UTC_TIME) - return MmsValue_getUtcTimeQuality(valueReference); - else - throw new MmsValueException("Value is not a time type"); - } - - /// - /// Sets the quality flags of an UTC timestamp - /// - /// - /// Meaning of the bits in the timeQuality byte: - /// bit 7 = leapSecondsKnown - /// bit 6 = clockFailure - /// bit 5 = clockNotSynchronized - /// bit 0-4 = subsecond time accuracy (number of significant bits of subsecond time) - /// - /// Time quality. - public void SetUtcTimeQuality(byte timeQuality) - { - if (GetType () == MmsType.MMS_UTC_TIME) - MmsValue_setUtcTimeQuality (valueReference, timeQuality); - else - throw new MmsValueException("Value is not a time type"); - } + public ulong GetUtcTimeInMs() + { + if (GetType() == MmsType.MMS_UTC_TIME) + { + return MmsValue_getUtcTimeInMs(valueReference); + } + else + throw new MmsValueException("Value is not a time type"); + } + + /// + /// Gets the timestamp value as UTC time in ms and the additional us part. + /// + /// + /// Return the value as milliseconds since epoch (1.1.1970 UTC) and the additional us part. + /// The value has to be of type MMS_UTC_TIME. + /// + /// + /// returns the usec part of the time value + /// + /// + /// The UTC time in ms. + /// + /// This exception is thrown if the value has the wrong type. + public ulong GetUtcTimeInMsWithUs(out int usec) + { + if (GetType() == MmsType.MMS_UTC_TIME) + { + uint uusec = 0; + var msVal = MmsValue_getUtcTimeInMsWithUs(valueReference, uusec); + usec = (int)uusec; + return msVal; + } + else + throw new MmsValueException("Value is not a time type"); + } + + /// + /// Gets quality flags of an UTC timestamp. + /// + /// + /// Meaning of the bits in the timeQuality byte: + /// bit 7 = leapSecondsKnown + /// bit 6 = clockFailure + /// bit 5 = clockNotSynchronized + /// bit 0-4 = subsecond time accuracy (number of significant bits of subsecond time) + /// + /// The UTC time quality. + public byte GetUtcTimeQuality() + { + if (GetType() == MmsType.MMS_UTC_TIME) + return MmsValue_getUtcTimeQuality(valueReference); + else + throw new MmsValueException("Value is not a time type"); + } + + /// + /// Sets the quality flags of an UTC timestamp + /// + /// + /// Meaning of the bits in the timeQuality byte: + /// bit 7 = leapSecondsKnown + /// bit 6 = clockFailure + /// bit 5 = clockNotSynchronized + /// bit 0-4 = subsecond time accuracy (number of significant bits of subsecond time) + /// + /// Time quality. + public void SetUtcTimeQuality(byte timeQuality) + { + if (GetType() == MmsType.MMS_UTC_TIME) + MmsValue_setUtcTimeQuality(valueReference, timeQuality); + else + throw new MmsValueException("Value is not a time type"); + } /// /// Convert a millisecond time (milliseconds since epoch) to DataTimeOffset @@ -791,12 +808,12 @@ namespace IEC61850 /// /// the millisecond time /// - public static DateTimeOffset MsTimeToDateTimeOffset (UInt64 msTime) - { - DateTimeOffset retVal = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero); - - return retVal.AddMilliseconds ((double) msTime); - } + public static DateTimeOffset MsTimeToDateTimeOffset(UInt64 msTime) + { + DateTimeOffset retVal = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); + + return retVal.AddMilliseconds(msTime); + } /// /// Convert MMS_UTC_TIME to DateTimeOffset instance @@ -809,13 +826,13 @@ namespace IEC61850 /// the value as DataTimeOffset instance /// /// This exception is thrown if the value has the wrong type. - public DateTimeOffset GetUtcTimeAsDateTimeOffset () - { - if (GetType () == MmsType.MMS_UTC_TIME) - return MsTimeToDateTimeOffset (GetUtcTimeInMs ()); - else - throw new MmsValueException ("Value is not a time type"); - } + public DateTimeOffset GetUtcTimeAsDateTimeOffset() + { + if (GetType() == MmsType.MMS_UTC_TIME) + return MsTimeToDateTimeOffset(GetUtcTimeInMs()); + else + throw new MmsValueException("Value is not a time type"); + } /// @@ -829,47 +846,47 @@ namespace IEC61850 /// the value if the object as 32 bit signed integer /// /// This exception is thrown if the value has the wrong type. - public Int32 ToInt32 () - { - if (GetType () != MmsType.MMS_INTEGER) - throw new MmsValueException ("Value type is not integer"); - - return MmsValue_toInt32 (valueReference); - } - - /// - /// Sets the 32 bit signed integer. - /// - /// - /// the new value to set - /// - /// This exception is thrown if the value has the wrong type. - public void SetInt32(int value) - { - if (GetType() != MmsType.MMS_INTEGER) - throw new MmsValueException("Value type is not integer"); - - MmsValue_setInt32(valueReference, value); - } - - /// - /// Return the value as 64 bit signed integer. - /// - /// - /// Return the value as 64 bit signed integer (Int64). - /// The value has to be of type MMS_INTEGER. - /// - /// - /// the value if the object as 64 bit signed integer - /// - /// This exception is thrown if the value has the wrong type. - public Int64 ToInt64 () - { - if (GetType () != MmsType.MMS_INTEGER) - throw new MmsValueException ("Value type is not integer"); - - return MmsValue_toInt64 (valueReference); - } + public Int32 ToInt32() + { + if (GetType() != MmsType.MMS_INTEGER) + throw new MmsValueException("Value type is not integer"); + + return MmsValue_toInt32(valueReference); + } + + /// + /// Sets the 32 bit signed integer. + /// + /// + /// the new value to set + /// + /// This exception is thrown if the value has the wrong type. + public void SetInt32(int value) + { + if (GetType() != MmsType.MMS_INTEGER) + throw new MmsValueException("Value type is not integer"); + + MmsValue_setInt32(valueReference, value); + } + + /// + /// Return the value as 64 bit signed integer. + /// + /// + /// Return the value as 64 bit signed integer (Int64). + /// The value has to be of type MMS_INTEGER. + /// + /// + /// the value if the object as 64 bit signed integer + /// + /// This exception is thrown if the value has the wrong type. + public Int64 ToInt64() + { + if (GetType() != MmsType.MMS_INTEGER) + throw new MmsValueException("Value type is not integer"); + + return MmsValue_toInt64(valueReference); + } /// /// Return the value as 32 bit unsigned integer. @@ -882,29 +899,29 @@ namespace IEC61850 /// the value if the object as 32 bit unsigned integer /// /// This exception is thrown if the value has the wrong type. - public UInt32 ToUint32 () - { - if (GetType () != MmsType.MMS_UNSIGNED) - throw new MmsValueException ("Value type is not unsigned"); - - return MmsValue_toUint32 (valueReference); - } - - public UInt32 BitStringToUInt32 () - { - if (GetType () != MmsType.MMS_BIT_STRING) - throw new MmsValueException("Value type is not bit string"); - - return MmsValue_getBitStringAsInteger(valueReference); - } - - public void BitStringFromUInt32 (UInt32 intValue) - { - if (GetType () != MmsType.MMS_BIT_STRING) - throw new MmsValueException("Value type is not bit string"); - - MmsValue_setBitStringFromInteger(valueReference, intValue); - } + public UInt32 ToUint32() + { + if (GetType() != MmsType.MMS_UNSIGNED) + throw new MmsValueException("Value type is not unsigned"); + + return MmsValue_toUint32(valueReference); + } + + public UInt32 BitStringToUInt32() + { + if (GetType() != MmsType.MMS_BIT_STRING) + throw new MmsValueException("Value type is not bit string"); + + return MmsValue_getBitStringAsInteger(valueReference); + } + + public void BitStringFromUInt32(UInt32 intValue) + { + if (GetType() != MmsType.MMS_BIT_STRING) + throw new MmsValueException("Value type is not bit string"); + + MmsValue_setBitStringFromInteger(valueReference, intValue); + } public UInt32 BitStringToUInt32BigEndian() { @@ -922,21 +939,21 @@ namespace IEC61850 MmsValue_setBitStringFromIntegerBigEndian(valueReference, intValue); } - public void SetBit (int bitPos, bool bitValue) - { - 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) - { - if (GetType () != MmsType.MMS_BIT_STRING) - throw new MmsValueException("Value type is not bit string"); - - return MmsValue_getBitStringBit(valueReference, bitPos); - } + public void SetBit(int bitPos, bool bitValue) + { + 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) + { + if (GetType() != MmsType.MMS_BIT_STRING) + throw new MmsValueException("Value type is not bit string"); + + return MmsValue_getBitStringBit(valueReference, bitPos); + } private string GetBitStringAsString() { @@ -965,58 +982,58 @@ namespace IEC61850 /// The boolean value /// /// This exception is thrown if the value has the wrong type. - public bool GetBoolean () - { - if (GetType () == MmsType.MMS_BOOLEAN) - return MmsValue_getBoolean (valueReference); - else - throw new MmsValueException ("Value type is not boolean"); - } - - /// - /// Sets the boolean value of an MMS_BOOLEAN instance - /// - /// - /// the new value to set - /// - /// This exception is thrown if the value has the wrong type. - public void SetBoolean(bool value) - { - if (GetType() != MmsType.MMS_BOOLEAN) - throw new MmsValueException("Value type is not boolean"); - - MmsValue_setBoolean(valueReference, value); - } - - /// - /// Gets the float value of an MMS_FLOAT instance - /// - /// - /// The float value - /// - /// This exception is thrown if the value has the wrong type. - public float ToFloat () - { - if (GetType () == MmsType.MMS_FLOAT) - return MmsValue_toFloat (valueReference); - else - throw new MmsValueException ("Value type is not float"); - } - - /// - /// Sets the float value of an MMS_FLOAT instance - /// - /// - /// the new value to set - /// - /// This exception is thrown if the value has the wrong type. - public void SetFloat (float value) - { - if (GetType () == MmsType.MMS_FLOAT) - MmsValue_setFloat (valueReference, value); - else - throw new MmsValueException ("Value type is not float"); - } + public bool GetBoolean() + { + if (GetType() == MmsType.MMS_BOOLEAN) + return MmsValue_getBoolean(valueReference); + else + throw new MmsValueException("Value type is not boolean"); + } + + /// + /// Sets the boolean value of an MMS_BOOLEAN instance + /// + /// + /// the new value to set + /// + /// This exception is thrown if the value has the wrong type. + public void SetBoolean(bool value) + { + if (GetType() != MmsType.MMS_BOOLEAN) + throw new MmsValueException("Value type is not boolean"); + + MmsValue_setBoolean(valueReference, value); + } + + /// + /// Gets the float value of an MMS_FLOAT instance + /// + /// + /// The float value + /// + /// This exception is thrown if the value has the wrong type. + public float ToFloat() + { + if (GetType() == MmsType.MMS_FLOAT) + return MmsValue_toFloat(valueReference); + else + throw new MmsValueException("Value type is not float"); + } + + /// + /// Sets the float value of an MMS_FLOAT instance + /// + /// + /// the new value to set + /// + /// This exception is thrown if the value has the wrong type. + public void SetFloat(float value) + { + if (GetType() == MmsType.MMS_FLOAT) + MmsValue_setFloat(valueReference, value); + else + throw new MmsValueException("Value type is not float"); + } /// /// Gets the double value of an MMS_FLOAT instance @@ -1025,28 +1042,28 @@ namespace IEC61850 /// The float value /// /// This exception is thrown if the value has the wrong type. - public double ToDouble () - { - if (GetType () == MmsType.MMS_FLOAT) - return MmsValue_toDouble (valueReference); - else - throw new MmsValueException ("Value type is not float"); - } - - /// - /// Sets the float/double value of an MMS_FLOAT instance - /// - /// - /// the new value to set - /// - /// This exception is thrown if the value has the wrong type. - public void SetDouble (double value) - { - if (GetType () == MmsType.MMS_FLOAT) - MmsValue_setDouble (valueReference, value); - else - throw new MmsValueException ("Value type is not float"); - } + public double ToDouble() + { + if (GetType() == MmsType.MMS_FLOAT) + return MmsValue_toDouble(valueReference); + else + throw new MmsValueException("Value type is not float"); + } + + /// + /// Sets the float/double value of an MMS_FLOAT instance + /// + /// + /// the new value to set + /// + /// This exception is thrown if the value has the wrong type. + public void SetDouble(double value) + { + if (GetType() == MmsType.MMS_FLOAT) + MmsValue_setDouble(valueReference, value); + else + throw new MmsValueException("Value type is not float"); + } /// /// Gets the child value with the given name @@ -1083,169 +1100,179 @@ namespace IEC61850 return new MmsValue(clonePtr, true); } - public override bool Equals (object obj) + public override bool Equals(object obj) { - MmsValue otherValue = (MmsValue) obj; - - return MmsValue_equals(this.valueReference, otherValue.valueReference); - } - - // override standard ToString() method - public override string ToString () - { - switch (GetType ()) { - case MmsType.MMS_VISIBLE_STRING: - case MmsType.MMS_STRING: - return Marshal.PtrToStringAnsi (MmsValue_toString (valueReference)); - case MmsType.MMS_BOOLEAN: - return GetBoolean ().ToString (); - case MmsType.MMS_INTEGER: - return ToInt64 ().ToString (); - case MmsType.MMS_UNSIGNED: - return ToUint32 ().ToString (); - case MmsType.MMS_FLOAT: - return ToDouble ().ToString (); - case MmsType.MMS_UTC_TIME: - return GetUtcTimeAsDateTimeOffset ().ToString (); - case MmsType.MMS_BINARY_TIME: - return (MsTimeToDateTimeOffset (GetBinaryTimeAsUtcMs ()).ToString ()); - case MmsType.MMS_OCTET_STRING: - return BitConverter.ToString (getOctetString ()); - case MmsType.MMS_BIT_STRING: - return GetBitStringAsString(); - case MmsType.MMS_STRUCTURE: - { - string retString = "{"; - - bool first = true; - - foreach (MmsValue element in this) { - if (first) { - retString += element.ToString (); - - first = false; - } else { - retString += ", " + element.ToString (); - } - } - - retString += "}"; - - return retString; - } - case MmsType.MMS_ARRAY: - { - string retString = "["; - - bool first = true; + MmsValue otherValue = (MmsValue)obj; - foreach (MmsValue element in this) { - if (first) { - retString += element.ToString (); - - first = false; - } else { - retString += ", " + element.ToString (); - } - } - - retString += "]"; - - return retString; - } - case MmsType.MMS_DATA_ACCESS_ERROR: - return "error: " + GetDataAccessError().ToString(); - - default: - return "unknown (type:" + GetType().ToString() + ")"; - } - } - - IEnumerator IEnumerable.GetEnumerator () - { - return new MmsValueEnumerator (this); - } - - private class MmsValueEnumerator : IEnumerator - { - private MmsValue value; - private int index = -1; - - public MmsValueEnumerator (MmsValue value) - { - this.value = value; - } - - #region IEnumerator Members - public void Reset () - { - index = -1; - } - - public object Current { - - get { return value.GetElement (index);} - } - - public bool MoveNext () - { - index++; - - if (index >= value.Size ()) - return false; - else - return true; - } - - #endregion - } - - } - - public class MmsValueException : Exception - { - public MmsValueException (string message) - : base(message) - { - } - } - - public enum MmsType - { - /** array type (multiple elements of the same type) */ - MMS_ARRAY = 0, - /** structure type (multiple elements of different types) */ - MMS_STRUCTURE = 1, - /** boolean */ - MMS_BOOLEAN = 2, - /** bit string */ - MMS_BIT_STRING = 3, - /** signed integer */ - MMS_INTEGER = 4, - /** unsigned integer */ - MMS_UNSIGNED = 5, - /** floating point value (32 or 64 bit) */ - MMS_FLOAT = 6, - /** octet string */ - MMS_OCTET_STRING = 7, - /** visible string - ANSI string */ - MMS_VISIBLE_STRING = 8, - /** Generalized time */ - MMS_GENERALIZED_TIME = 9, - /** Binary time */ - MMS_BINARY_TIME = 10, - /** Binary coded decimal (BCD) - not used */ - MMS_BCD = 11, - /** object ID - not used */ - MMS_OBJ_ID = 12, - /** Unicode string */ - MMS_STRING = 13, - /** UTC time */ - MMS_UTC_TIME = 14, - /** will be returned in case of an error (contains error code) */ - MMS_DATA_ACCESS_ERROR = 15 - } - - } + return MmsValue_equals(valueReference, otherValue.valueReference); + } + + // override standard ToString() method + public override string ToString() + { + switch (GetType()) + { + case MmsType.MMS_VISIBLE_STRING: + case MmsType.MMS_STRING: + return Marshal.PtrToStringAnsi(MmsValue_toString(valueReference)); + case MmsType.MMS_BOOLEAN: + return GetBoolean().ToString(); + case MmsType.MMS_INTEGER: + return ToInt64().ToString(); + case MmsType.MMS_UNSIGNED: + return ToUint32().ToString(); + case MmsType.MMS_FLOAT: + return ToDouble().ToString(); + case MmsType.MMS_UTC_TIME: + return GetUtcTimeAsDateTimeOffset().ToString(); + case MmsType.MMS_BINARY_TIME: + return (MsTimeToDateTimeOffset(GetBinaryTimeAsUtcMs()).ToString()); + case MmsType.MMS_OCTET_STRING: + return BitConverter.ToString(getOctetString()); + case MmsType.MMS_BIT_STRING: + return GetBitStringAsString(); + case MmsType.MMS_STRUCTURE: + { + string retString = "{"; + + bool first = true; + + foreach (MmsValue element in this) + { + if (first) + { + retString += element.ToString(); + + first = false; + } + else + { + retString += ", " + element.ToString(); + } + } + + retString += "}"; + + return retString; + } + case MmsType.MMS_ARRAY: + { + string retString = "["; + + bool first = true; + + foreach (MmsValue element in this) + { + if (first) + { + retString += element.ToString(); + + first = false; + } + else + { + retString += ", " + element.ToString(); + } + } + + retString += "]"; + + return retString; + } + case MmsType.MMS_DATA_ACCESS_ERROR: + return "error: " + GetDataAccessError().ToString(); + + default: + return "unknown (type:" + GetType().ToString() + ")"; + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return new MmsValueEnumerator(this); + } + + private class MmsValueEnumerator : IEnumerator + { + private MmsValue value; + private int index = -1; + + public MmsValueEnumerator(MmsValue value) + { + this.value = value; + } + + #region IEnumerator Members + public void Reset() + { + index = -1; + } + + public object Current + { + + get { return value.GetElement(index); } + } + + public bool MoveNext() + { + index++; + + if (index >= value.Size()) + return false; + else + return true; + } + + #endregion + } + + } + + public class MmsValueException : Exception + { + public MmsValueException(string message) + : base(message) + { + } + } + + public enum MmsType + { + /** array type (multiple elements of the same type) */ + MMS_ARRAY = 0, + /** structure type (multiple elements of different types) */ + MMS_STRUCTURE = 1, + /** boolean */ + MMS_BOOLEAN = 2, + /** bit string */ + MMS_BIT_STRING = 3, + /** signed integer */ + MMS_INTEGER = 4, + /** unsigned integer */ + MMS_UNSIGNED = 5, + /** floating point value (32 or 64 bit) */ + MMS_FLOAT = 6, + /** octet string */ + MMS_OCTET_STRING = 7, + /** visible string - ANSI string */ + MMS_VISIBLE_STRING = 8, + /** Generalized time */ + MMS_GENERALIZED_TIME = 9, + /** Binary time */ + MMS_BINARY_TIME = 10, + /** Binary coded decimal (BCD) - not used */ + MMS_BCD = 11, + /** object ID - not used */ + MMS_OBJ_ID = 12, + /** Unicode string */ + MMS_STRING = 13, + /** UTC time */ + MMS_UTC_TIME = 14, + /** will be returned in case of an error (contains error code) */ + MMS_DATA_ACCESS_ERROR = 15 + } + + } } diff --git a/dotnet/IEC61850forCSharp/MmsVariableSpecification.cs b/dotnet/IEC61850forCSharp/MmsVariableSpecification.cs index fb8cac76..a93ea53e 100644 --- a/dotnet/IEC61850forCSharp/MmsVariableSpecification.cs +++ b/dotnet/IEC61850forCSharp/MmsVariableSpecification.cs @@ -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; } diff --git a/dotnet/IEC61850forCSharp/ReportControlBlock.cs b/dotnet/IEC61850forCSharp/ReportControlBlock.cs index 22b61808..c931597d 100644 --- a/dotnet/IEC61850forCSharp/ReportControlBlock.cs +++ b/dotnet/IEC61850forCSharp/ReportControlBlock.cs @@ -1,7 +1,7 @@ /* * ReportControlBlock.cs * - * Copyright 2014-2018 Michael Zillgith + * Copyright 2014-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -20,26 +20,24 @@ * * 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 - { + namespace Client + { /// /// Report handler. /// /// represents the received report. DON'T use this object /// outside the scope of the report handler! - 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); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void InternalReportHandler(IntPtr parameter, IntPtr report); /// /// Report control block (RCB) representation. @@ -50,214 +48,219 @@ namespace IEC61850 /// Values at the server are only affected when the SetRCBValues method is called. /// public class ReportControlBlock : IDisposable - { - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientReportControlBlock_create (string dataAttributeReference); + { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientReportControlBlock_create(string dataAttributeReference); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientReportControlBlock_destroy (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_destroy(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientReportControlBlock_getRptId(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientReportControlBlock_setRptId (IntPtr self, string rptId); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setRptId(IntPtr self, string rptId); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [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)] + static extern void ClientReportControlBlock_setRptEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setResv(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool resv); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientReportControlBlock_getDataSetReference (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientReportControlBlock_getDataSetReference(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientReportControlBlock_setDataSetReference (IntPtr self, string dataSetReference); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setDataSetReference(IntPtr self, string dataSetReference); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 ClientReportControlBlock_getConfRev (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 ClientReportControlBlock_getConfRev(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern int ClientReportControlBlock_getOptFlds (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int ClientReportControlBlock_getOptFlds(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientReportControlBlock_setOptFlds (IntPtr self, int optFlds); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setOptFlds(IntPtr self, int optFlds); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 ClientReportControlBlock_getBufTm (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 ClientReportControlBlock_getBufTm(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientReportControlBlock_setBufTm (IntPtr self, UInt32 bufTm); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setBufTm(IntPtr self, UInt32 bufTm); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt16 ClientReportControlBlock_getSqNum (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt16 ClientReportControlBlock_getSqNum(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern int ClientReportControlBlock_getTrgOps (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int ClientReportControlBlock_getTrgOps(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientReportControlBlock_setTrgOps (IntPtr self, int trgOps); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setTrgOps(IntPtr self, int trgOps); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 ClientReportControlBlock_getIntgPd (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 ClientReportControlBlock_getIntgPd(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientReportControlBlock_setIntgPd (IntPtr self, UInt32 intgPd); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setIntgPd(IntPtr self, UInt32 intgPd); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setGI(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool gi); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setResvTms(IntPtr self, Int16 resvTms); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientReportControlBlock_getEntryId (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientReportControlBlock_getEntryId(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern void ClientReportControlBlock_setEntryId (IntPtr self, IntPtr entryId); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientReportControlBlock_setEntryId(IntPtr self, IntPtr entryId); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt64 ClientReportControlBlock_getEntryTime (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt64 ClientReportControlBlock_getEntryTime(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientReportControlBlock_getOwner (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientReportControlBlock_getOwner(IntPtr self); + + internal IntPtr self; - internal IntPtr self; - private IedConnection iedConnection = null; - private string objectReference; - private bool flagRptId = false; - private bool flagRptEna = false; - private bool flagResv = false; - private bool flagDataSetReference = false; - private bool flagConfRev = false; - private bool flagOptFlds = false; - private bool flagBufTm = false; - private bool flagSqNum = false; - private bool flagTrgOps = false; - private bool flagIntgPd = false; - private bool flagGI = false; - private bool flagPurgeBuf = false; - private bool flagResvTms = false; - private bool flagEntryId = false; - - private event ReportHandler reportHandler = null; - private object reportHandlerParameter; - private bool reportHandlerInstalled = false; + private string objectReference; + private bool flagRptId = false; + private bool flagRptEna = false; + private bool flagResv = false; + private bool flagDataSetReference = false; + private bool flagConfRev = false; + private bool flagOptFlds = false; + private bool flagBufTm = false; + private bool flagSqNum = false; + private bool flagTrgOps = false; + private bool flagIntgPd = false; + private bool flagGI = false; + private bool flagPurgeBuf = false; + private bool flagResvTms = false; + private bool flagEntryId = false; + + private event ReportHandler reportHandler = null; + private object reportHandlerParameter; + private bool reportHandlerInstalled = false; private event InternalReportHandler internalHandler = null; - private void resetSendFlags () - { - flagRptId = false; - flagRptEna = false; - flagResv = false; - flagDataSetReference = false; - flagConfRev = false; - flagOptFlds = false; - flagBufTm = false; - flagSqNum = false; - flagTrgOps = false; - flagIntgPd = false; - flagGI = false; - flagPurgeBuf = false; - flagResvTms = false; - flagEntryId = false; - } - - private Report report = null; - - private void internalReportHandler (IntPtr parameter, IntPtr report) - { - try { - - if (this.report == null) - this.report = new Report (report); - - if (reportHandler != null) - reportHandler(this.report, reportHandlerParameter); - - } 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) - { - self = ClientReportControlBlock_create (objectReference); - - if (self != IntPtr.Zero) { - this.iedConnection = iedConnection; - this.objectReference = objectReference; - } - } - - /// - /// Releases all resource used by the object. - /// - /// Call when you are finished using the . The - /// method leaves the in an unusable state. - /// After calling , you must release all references to the - /// so the garbage collector can reclaim the memory that the - /// was occupying. - public void Dispose() - { - lock (this) { - if (self != IntPtr.Zero) { - - iedConnection.UninstallReportHandler (objectReference); - - iedConnection.RemoveRCB (this); - - ClientReportControlBlock_destroy (self); - - self = IntPtr.Zero; - } - } - } - - ~ReportControlBlock() - { - Dispose (); - } - - public string GetObjectReference () - { - return this.objectReference; - } - + private void resetSendFlags() + { + flagRptId = false; + flagRptEna = false; + flagResv = false; + flagDataSetReference = false; + flagConfRev = false; + flagOptFlds = false; + flagBufTm = false; + flagSqNum = false; + flagTrgOps = false; + flagIntgPd = false; + flagGI = false; + flagPurgeBuf = false; + flagResvTms = false; + flagEntryId = false; + } + + private Report report = null; + + private void internalReportHandler(IntPtr parameter, IntPtr report) + { + try + { + + if (this.report == null) + this.report = new Report(report); + + if (reportHandler != null) + reportHandler(this.report, reportHandlerParameter); + + } + 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) + { + self = ClientReportControlBlock_create(objectReference); + + if (self != IntPtr.Zero) + { + this.iedConnection = iedConnection; + this.objectReference = objectReference; + } + } + + /// + /// Releases all resource used by the object. + /// + /// Call when you are finished using the . The + /// method leaves the in an unusable state. + /// After calling , you must release all references to the + /// so the garbage collector can reclaim the memory that the + /// was occupying. + public void Dispose() + { + lock (this) + { + if (self != IntPtr.Zero) + { + + iedConnection.UninstallReportHandler(objectReference); + + iedConnection.RemoveRCB(this); + + ClientReportControlBlock_destroy(self); + + self = IntPtr.Zero; + } + } + } + + ~ReportControlBlock() + { + Dispose(); + } + + public string GetObjectReference() + { + return objectReference; + } + /// /// Installs the report handler. /// @@ -272,40 +275,41 @@ namespace IEC61850 /// /// parameter is passed to the handler when the handler is invoked. /// - public void InstallReportHandler (ReportHandler reportHandler, object parameter) - { - this.reportHandler = new ReportHandler(reportHandler); + 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); + internalHandler = new InternalReportHandler(internalReportHandler); } - - iedConnection.InstallReportHandler (objectReference, reportId, internalHandler); - reportHandlerInstalled = true; - } - } + iedConnection.InstallReportHandler(objectReference, reportId, internalHandler); + + reportHandlerInstalled = true; + } + } /// /// Read all RCB values from the server /// /// This exception is thrown if there is a connection or service error - public void GetRCBValues () - { - int error; + 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); - } + if (error != 0) + throw new IedConnectionException("getRCBValues service failed", error); + } /// /// Read all RCB values from the server - asynchronous version @@ -327,10 +331,10 @@ namespace IEC61850 /// The RCB values are sent by a single MMS write request. /// /// This exception is thrown if there is a connection or service error - public void SetRCBValues () - { - SetRCBValues (true); - } + public void SetRCBValues() + { + SetRCBValues(true); + } private UInt32 CreateParametersMask() { @@ -382,12 +386,12 @@ namespace IEC61850 } public UInt32 SetRCBValuesAsync(SetRCBValuesHandler handler, object parameter) - { + { return SetRCBValuesAsync(true, handler, parameter); } public UInt32 SetRCBValuesAsync(bool singleRequest, SetRCBValuesHandler handler, object parameter) - { + { UInt32 parametersMask = CreateParametersMask(); return iedConnection.SetRCBValuesAsync(this, parametersMask, singleRequest, handler, parameter); @@ -403,7 +407,7 @@ namespace IEC61850 /// /// If true the values are sent by single MMS write request. Otherwise the values are all sent by their own MMS write requests. /// - public void SetRCBValues (bool singleRequest) + public void SetRCBValues(bool singleRequest) { UInt32 parametersMask = CreateParametersMask(); @@ -411,21 +415,23 @@ namespace IEC61850 int error; - iedConnection.SetRCBValues (out error, self, parametersMask, singleRequest); - - resetSendFlags(); + 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); } } - } + } /// /// Determines whether this instance is a buffered or unbuffered RCB. @@ -433,10 +439,10 @@ namespace IEC61850 /// /// true if this instance is a buffered RCB; otherwise, false. /// - public bool IsBuffered () - { - return ClientReportControlBlock_isBuffered (self); - } + public bool IsBuffered() + { + return ClientReportControlBlock_isBuffered(self); + } /// /// Gets the entry time of the RCB as ms time @@ -447,10 +453,10 @@ namespace IEC61850 /// /// The entry time as ms timestamp /// - public UInt64 GetEntryTime () - { - return ClientReportControlBlock_getEntryTime (self); - } + public UInt64 GetEntryTime() + { + return ClientReportControlBlock_getEntryTime(self); + } /// /// Gets the entry time of the RCB as DateTimeOffset @@ -461,49 +467,50 @@ namespace IEC61850 /// /// The entry time as DataTimeOffset /// - public DateTimeOffset GetEntryTimeAsDateTimeOffset () - { - UInt64 entryTime = GetEntryTime (); + public DateTimeOffset GetEntryTimeAsDateTimeOffset() + { + 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); + } - /// - /// Gets the entryID of RCB - /// - /// Returns the EntryID of the last received GetRCBValues service response. - /// The EntryID is only present in buffered RCBs (BRCBs). - /// - /// The entry ID - public byte[] GetEntryID() - { - IntPtr entryIdRef = ClientReportControlBlock_getEntryId (self); + /// + /// Gets the entryID of RCB + /// + /// Returns the EntryID of the last received GetRCBValues service response. + /// The EntryID is only present in buffered RCBs (BRCBs). + /// + /// The entry ID + public byte[] GetEntryID() + { + IntPtr entryIdRef = ClientReportControlBlock_getEntryId(self); - if (entryIdRef == IntPtr.Zero) - return null; - else { - MmsValue entryId = new MmsValue (entryIdRef); + if (entryIdRef == IntPtr.Zero) + return null; + else + { + MmsValue entryId = new MmsValue(entryIdRef); - return entryId.getOctetString (); - } - } + return entryId.getOctetString(); + } + } - public void SetEntryID(byte[] entryId) - { - flagEntryId = true; + public void SetEntryID(byte[] entryId) + { + flagEntryId = true; - 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,12 +519,12 @@ namespace IEC61850 /// /// The data set reference. /// - public string GetDataSetReference () - { - IntPtr dataSetRefPtr = ClientReportControlBlock_getDataSetReference (self); + public string GetDataSetReference() + { + IntPtr dataSetRefPtr = ClientReportControlBlock_getDataSetReference(self); - return Marshal.PtrToStringAnsi (dataSetRefPtr); - } + return Marshal.PtrToStringAnsi(dataSetRefPtr); + } /// /// Sets the data set reference. Use this method to select the associated data set for the RCB @@ -525,12 +532,12 @@ namespace IEC61850 /// /// The data set reference. /// - public void SetDataSetReference (string dataSetReference) - { - ClientReportControlBlock_setDataSetReference (self, dataSetReference); + public void SetDataSetReference(string dataSetReference) + { + ClientReportControlBlock_setDataSetReference(self, dataSetReference); - flagDataSetReference = true; - } + flagDataSetReference = true; + } /// /// Gets the report identifier. @@ -538,12 +545,12 @@ namespace IEC61850 /// /// The report identifier. /// - public string GetRptId () - { - IntPtr rptIdPtr = ClientReportControlBlock_getRptId (self); + public string GetRptId() + { + IntPtr rptIdPtr = ClientReportControlBlock_getRptId(self); - return Marshal.PtrToStringAnsi (rptIdPtr); - } + return Marshal.PtrToStringAnsi(rptIdPtr); + } /// /// Sets the RptId (report ID) of the RCB @@ -551,7 +558,7 @@ namespace IEC61850 /// /// The new RptId /// - public void SetRptId (string rptId) + public void SetRptId(string rptId) { ClientReportControlBlock_setRptId(self, rptId); flagRptId = true; @@ -563,10 +570,10 @@ namespace IEC61850 /// /// true, if reporting is enabled, false otherwise /// - public bool GetRptEna () - { - return ClientReportControlBlock_getRptEna (self); - } + public bool GetRptEna() + { + return ClientReportControlBlock_getRptEna(self); + } /// /// Sets report enable flag. Use this to enable reporting @@ -574,17 +581,17 @@ namespace IEC61850 /// /// true to enable reporting, false to disable /// - public void SetRptEna (bool rptEna) - { - ClientReportControlBlock_setRptEna (self, rptEna); - flagRptEna = true; - } + public void SetRptEna(bool rptEna) + { + ClientReportControlBlock_setRptEna(self, rptEna); + flagRptEna = true; + } /// /// Get the purgeBuf flag of the report control block /// /// the prugeBuf value - public bool GetPurgeBuf () + public bool GetPurgeBuf() { return ClientReportControlBlock_getPurgeBuf(self); } @@ -594,7 +601,7 @@ namespace IEC61850 /// /// This is only for buffered RCBs. If set to true the report buffer of a buffered RCB will be cleaned. /// set to true to flush report buffer - public void SetPurgeBuf (bool purgeBuf) + public void SetPurgeBuf(bool purgeBuf) { ClientReportControlBlock_setPurgeBuf(self, purgeBuf); flagPurgeBuf = true; @@ -606,10 +613,10 @@ namespace IEC61850 /// /// The buffer time in ms. /// - public UInt32 GetBufTm() - { - return ClientReportControlBlock_getBufTm (self); - } + public UInt32 GetBufTm() + { + return ClientReportControlBlock_getBufTm(self); + } /// /// Sets the buffer time. @@ -617,12 +624,12 @@ namespace IEC61850 /// /// Buffer time is ms. /// - public void SetBufTm (UInt32 bufTm) - { - ClientReportControlBlock_setBufTm (self, bufTm); + public void SetBufTm(UInt32 bufTm) + { + ClientReportControlBlock_setBufTm(self, bufTm); - flagBufTm = true; - } + flagBufTm = true; + } /// /// Gets the GI flag @@ -630,10 +637,10 @@ namespace IEC61850 /// /// true, if GI flag is set /// - public bool GetGI () - { - return ClientReportControlBlock_getGI (self); - } + public bool GetGI() + { + return ClientReportControlBlock_getGI(self); + } /// /// Sets the GI flag. Use this to trigger a GI (general interrogation) command. @@ -641,11 +648,11 @@ namespace IEC61850 /// /// request general interrogation of true /// - public void SetGI (bool GI) - { - ClientReportControlBlock_setGI (self, GI); - flagGI = true; - } + public void SetGI(bool GI) + { + ClientReportControlBlock_setGI(self, GI); + flagGI = true; + } /// /// Check if RCB is reserved by a client @@ -653,10 +660,10 @@ namespace IEC61850 /// /// true, the RCB is reserver by a client /// - public bool GetResv () - { - return ClientReportControlBlock_getResv (self); - } + public bool GetResv() + { + return ClientReportControlBlock_getResv(self); + } /// /// Gets the configuration revision of the RCB @@ -664,9 +671,9 @@ namespace IEC61850 /// /// The conf rev. /// - public UInt32 GetConfRev () + public UInt32 GetConfRev() { - return ClientReportControlBlock_getConfRev (self); + return ClientReportControlBlock_getConfRev(self); } /// @@ -675,11 +682,11 @@ namespace IEC61850 /// /// true: reserver this RCB for exclusive use /// - public void SetResv (bool resv) - { - ClientReportControlBlock_setResv (self, resv); - flagResv = true; - } + public void SetResv(bool resv) + { + ClientReportControlBlock_setResv(self, resv); + flagResv = true; + } /// /// Gets the trigger options of the RCB @@ -688,9 +695,9 @@ namespace IEC61850 /// trigger options /// public TriggerOptions GetTrgOps() - { - return (TriggerOptions) ClientReportControlBlock_getTrgOps (self); - } + { + return (TriggerOptions)ClientReportControlBlock_getTrgOps(self); + } /// /// Sets the trigger options of the RCB. @@ -699,11 +706,11 @@ namespace IEC61850 /// trigger options /// public void SetTrgOps(TriggerOptions trgOps) - { - ClientReportControlBlock_setTrgOps (self, (int) trgOps); + { + ClientReportControlBlock_setTrgOps(self, (int)trgOps); - flagTrgOps = true; - } + flagTrgOps = true; + } /// /// Gets the integrity period @@ -711,10 +718,10 @@ namespace IEC61850 /// /// integrity period in ms /// - public UInt32 GetIntgPd () - { - return ClientReportControlBlock_getIntgPd (self); - } + public UInt32 GetIntgPd() + { + return ClientReportControlBlock_getIntgPd(self); + } /// /// Sets the integrity period @@ -722,11 +729,11 @@ namespace IEC61850 /// /// integrity period in ms /// - public void SetIntgPd (UInt32 intgPd) - { - ClientReportControlBlock_setIntgPd (self, intgPd); - flagIntgPd = true; - } + public void SetIntgPd(UInt32 intgPd) + { + ClientReportControlBlock_setIntgPd(self, intgPd); + flagIntgPd = true; + } /// /// Gets the option fields. @@ -735,9 +742,9 @@ namespace IEC61850 /// The option fields /// public ReportOptions GetOptFlds() - { - return (ReportOptions) ClientReportControlBlock_getOptFlds (self); - } + { + return (ReportOptions)ClientReportControlBlock_getOptFlds(self); + } /// /// Sets the option field. Used to enable or disable optional report elements @@ -746,11 +753,11 @@ namespace IEC61850 /// Option field. /// public void SetOptFlds(ReportOptions optFlds) - { - ClientReportControlBlock_setOptFlds (self, (int)optFlds); + { + ClientReportControlBlock_setOptFlds(self, (int)optFlds); - flagOptFlds = true; - } + flagOptFlds = true; + } /// /// Check if the report control block has the "ResvTms" attribute. @@ -805,7 +812,7 @@ namespace IEC61850 else return null; } - } + } - } + } } diff --git a/dotnet/IEC61850forCSharp/Reporting.cs b/dotnet/IEC61850forCSharp/Reporting.cs index 79a5ac55..3db3c55b 100644 --- a/dotnet/IEC61850forCSharp/Reporting.cs +++ b/dotnet/IEC61850forCSharp/Reporting.cs @@ -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 { diff --git a/dotnet/IEC61850forCSharp/SampledValuesControlBlock.cs b/dotnet/IEC61850forCSharp/SampledValuesControlBlock.cs index 733c2fb1..4d98145a 100644 --- a/dotnet/IEC61850forCSharp/SampledValuesControlBlock.cs +++ b/dotnet/IEC61850forCSharp/SampledValuesControlBlock.cs @@ -1,7 +1,7 @@ /* * SampledValuesControlBlock.cs * - * Copyright 2017 Michael Zillgith + * Copyright 2017-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -20,185 +20,184 @@ * * 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 - { - /// - /// Sampled values control bloc (SvCB) representation. - /// - /// - /// This class is used as a client side representation (copy) of a sampled values control block (SvCB). - /// - public class SampledValuesControlBlock : IDisposable - { - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientSVControlBlock_create (IntPtr iedConnection, string reference); + namespace Client + { + /// + /// Sampled values control bloc (SvCB) representation. + /// + /// + /// This class is used as a client side representation (copy) of a sampled values control block (SvCB). + /// + public class SampledValuesControlBlock : IDisposable + { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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 void ClientSVControlBlock_destroy(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern int ClientSVControlBlock_getLastComError (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int ClientSVControlBlock_getLastComError(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - static extern bool ClientSVControlBlock_isMulticast (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + 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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + 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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + 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); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool ClientSVControlBlock_getSvEna(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - static extern bool ClientSVControlBlock_getResv (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool ClientSVControlBlock_getResv(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientSVControlBlock_getMsvID (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientSVControlBlock_getMsvID(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr ClientSVControlBlock_getDatSet (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientSVControlBlock_getDatSet(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt32 ClientSVControlBlock_getConfRev (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt32 ClientSVControlBlock_getConfRev(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern UInt16 ClientSVControlBlock_getSmpRate (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern UInt16 ClientSVControlBlock_getSmpRate(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern int ClientSVControlBlock_getOptFlds (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + 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 byte ClientSVControlBlock_getSmpMod(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern int ClientSVControlBlock_getNoASDU (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern int ClientSVControlBlock_getNoASDU(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - static extern PhyComAddress ClientSVControlBlock_getDstAddress (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern PhyComAddress ClientSVControlBlock_getDstAddress(IntPtr self); - private IntPtr self; - private string objectReference; + private IntPtr self; + private string objectReference; - private bool isDisposed = false; + 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); - this.objectReference = objectReference; - } - - public string GetObjectReference () - { - return this.objectReference; - } - - public IedClientError GetLastComError() - { - return (IedClientError)ClientSVControlBlock_getLastComError (self); - } - - public bool IsMulticast() - { - return ClientSVControlBlock_isMulticast (self); - } - - public bool GetResv() - { - return ClientSVControlBlock_getResv (self); - } - - public bool SetResv(bool value) - { - return ClientSVControlBlock_setResv (self, value); - } - - public bool GetSvEna() - { - return ClientSVControlBlock_getSvEna (self); - } - - public bool SetSvEna(bool value) - { - return ClientSVControlBlock_setSvEna (self, value); - } - - public string GetMsvID () - { - IntPtr msvIdPtr = ClientSVControlBlock_getMsvID (self); - - return Marshal.PtrToStringAnsi (msvIdPtr); - } - - public string GetDatSet () - { - IntPtr datSetPtr = ClientSVControlBlock_getDatSet (self); - - return Marshal.PtrToStringAnsi (datSetPtr); - } - - public UInt32 GetConfRev () - { - return ClientSVControlBlock_getConfRev (self); - } - - public UInt16 GetSmpRate () - { - return ClientSVControlBlock_getSmpRate (self); - } - - public SVOptions GetOptFlds () - { - return (SVOptions)ClientSVControlBlock_getOptFlds (self); - } - - public SmpMod GetSmpMod () - { - return (SmpMod)ClientSVControlBlock_getSmpMod (self); - } - - public int GetNoASDU () - { - return ClientSVControlBlock_getNoASDU (self); - } - - public PhyComAddress GetDstAddress() - { - return ClientSVControlBlock_getDstAddress (self); - } - - public void Dispose() - { - if (isDisposed == false) { - isDisposed = true; - ClientSVControlBlock_destroy (self); - self = IntPtr.Zero; - } - } - - ~SampledValuesControlBlock() - { - Dispose (); - } - - } - - - } + { + self = ClientSVControlBlock_create(iedConnection, objectReference); + this.objectReference = objectReference; + } + + public string GetObjectReference() + { + return objectReference; + } + + public IedClientError GetLastComError() + { + return (IedClientError)ClientSVControlBlock_getLastComError(self); + } + + public bool IsMulticast() + { + return ClientSVControlBlock_isMulticast(self); + } + + public bool GetResv() + { + return ClientSVControlBlock_getResv(self); + } + + public bool SetResv(bool value) + { + return ClientSVControlBlock_setResv(self, value); + } + + public bool GetSvEna() + { + return ClientSVControlBlock_getSvEna(self); + } + + public bool SetSvEna(bool value) + { + return ClientSVControlBlock_setSvEna(self, value); + } + + public string GetMsvID() + { + IntPtr msvIdPtr = ClientSVControlBlock_getMsvID(self); + + return Marshal.PtrToStringAnsi(msvIdPtr); + } + + public string GetDatSet() + { + IntPtr datSetPtr = ClientSVControlBlock_getDatSet(self); + + return Marshal.PtrToStringAnsi(datSetPtr); + } + + public UInt32 GetConfRev() + { + return ClientSVControlBlock_getConfRev(self); + } + + public UInt16 GetSmpRate() + { + return ClientSVControlBlock_getSmpRate(self); + } + + public SVOptions GetOptFlds() + { + return (SVOptions)ClientSVControlBlock_getOptFlds(self); + } + + public SmpMod GetSmpMod() + { + return (SmpMod)ClientSVControlBlock_getSmpMod(self); + } + + public int GetNoASDU() + { + return ClientSVControlBlock_getNoASDU(self); + } + + public PhyComAddress GetDstAddress() + { + return ClientSVControlBlock_getDstAddress(self); + } + + public void Dispose() + { + if (isDisposed == false) + { + isDisposed = true; + ClientSVControlBlock_destroy(self); + self = IntPtr.Zero; + } + } + + ~SampledValuesControlBlock() + { + Dispose(); + } + + } + + + } } diff --git a/dotnet/IEC61850forCSharp/SampledValuesSubscriber.cs b/dotnet/IEC61850forCSharp/SampledValuesSubscriber.cs index 5da087a0..b6fb99cc 100644 --- a/dotnet/IEC61850forCSharp/SampledValuesSubscriber.cs +++ b/dotnet/IEC61850forCSharp/SampledValuesSubscriber.cs @@ -1,7 +1,7 @@ /* * SampledValuedSubscriber.cs * - * Copyright 2017 Michael Zillgith + * Copyright 2017-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -21,454 +21,463 @@ * See COPYING file for the complete license text. */ +using IEC61850.Common; using System; using System.Runtime.InteropServices; -using IEC61850.Common; namespace IEC61850 { - namespace SV - { - - namespace Subscriber - { - /// - /// SV receiver. - /// - /// A receiver is responsible for processing all SV message for a single Ethernet interface. - /// In order to process messages from multiple Ethernet interfaces you have to create multiple - /// instances. - public class SVReceiver : IDisposable - { - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr SVReceiver_create (); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVReceiver_disableDestAddrCheck(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVReceiver_enableDestAddrCheck(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVReceiver_addSubscriber(IntPtr self, IntPtr subscriber); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVReceiver_removeSubscriber(IntPtr self, IntPtr subscriber); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVReceiver_start(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVReceiver_stop(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool SVReceiver_isRunning (IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVReceiver_destroy(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVReceiver_setInterfaceId(IntPtr self, string interfaceId); - - private IntPtr self; - - private bool isDisposed = false; - - /// - /// Initializes a new instance of the class. - /// - - public SVReceiver() - { - self = SVReceiver_create (); - } - - public void SetInterfaceId(string interfaceId) - { - SVReceiver_setInterfaceId (self, interfaceId); - } - - public void DisableDestAddrCheck() - { - SVReceiver_disableDestAddrCheck (self); - } - - public void EnableDestAddrCheck() - { - SVReceiver_enableDestAddrCheck (self); - } - - /// - /// Add a subscriber to handle - /// - /// Subscriber. - public void AddSubscriber(SVSubscriber subscriber) - { - SVReceiver_addSubscriber (self, subscriber.self); - } - - - public void RemoveSubscriber(SVSubscriber subscriber) - { - SVReceiver_removeSubscriber (self, subscriber.self); - } - - /// - /// Start handling SV messages - /// - public void Start() - { - SVReceiver_start (self); - } - - /// - /// Stop handling SV messges - /// - public void Stop() - { - SVReceiver_stop (self); - } - - public bool IsRunning() - { - return SVReceiver_isRunning (self); - } - - /// - /// Releases all resource used by the object. - /// - /// Call when you are finished using the . The - /// method leaves the in an unusable state. - /// After calling , you must release all references to the - /// so the garbage collector can reclaim the memory that the - /// was occupying. - public void Dispose() - { - if (isDisposed == false) { - isDisposed = true; - SVReceiver_destroy (self); - self = IntPtr.Zero; - } - } - - ~SVReceiver() - { - Dispose (); - } - } - - - /// - /// SV listener. - /// - public delegate void SVUpdateListener (SVSubscriber report, object parameter, SVSubscriberASDU asdu); - - /// - /// Sampled Values (SV) Subscriber - /// - /// A subscriber is an instance associated with a single stream of measurement data. It is identified - /// by the Ethernet destination address, the appID value (both are on SV message level) and the svID value - /// that is part of each ASDU. - /// - public class SVSubscriber : IDisposable - { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - 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); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr SVSubscriber_create(IntPtr ethAddr, UInt16 appID); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVSubscriber_setListener(IntPtr self, InternalSVUpdateListener listener, IntPtr parameter); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern void SVSubscriber_destroy(IntPtr self); - - internal IntPtr self; - - private bool isDisposed = false; - - private SVUpdateListener listener; - private object listenerParameter = null; - - private event InternalSVUpdateListener internalListener = null; - - private void internalSVUpdateListener (IntPtr subscriber, IntPtr parameter, IntPtr asdu) - { - try { - - if (listener != null) { - listener(this, listenerParameter, new SVSubscriberASDU(asdu)); - } - - } - catch (Exception e) { - // older versions of mono 2.10 (for linux?) cause this exception - Console.WriteLine(e.Message); - } - } - - public SVSubscriber(byte[] ethAddr, UInt16 appID) - { - 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"); - - self = SVSubscriber_create (ethAddr, appID); - } - } - - public void SetListener(SVUpdateListener listener, object parameter) - { - this.listener = listener; - this.listenerParameter = parameter; - - if (internalListener == null) { - internalListener = new InternalSVUpdateListener (internalSVUpdateListener); - - SVSubscriber_setListener (self, internalListener, IntPtr.Zero); - } - } - - public void Dispose() - { - if (isDisposed == false) { - isDisposed = true; - SVSubscriber_destroy (self); - self = IntPtr.Zero; - } - } - } - - - public class SVSubscriberASDU - { - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt16 SVSubscriber_ASDU_getSmpCnt(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr SVSubscriber_ASDU_getSvId(IntPtr self); + namespace SV + { + + namespace Subscriber + { + /// + /// SV receiver. + /// + /// A receiver is responsible for processing all SV message for a single Ethernet interface. + /// In order to process messages from multiple Ethernet interfaces you have to create multiple + /// instances. + public class SVReceiver : IDisposable + { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr SVReceiver_create(); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVReceiver_disableDestAddrCheck(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVReceiver_enableDestAddrCheck(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVReceiver_addSubscriber(IntPtr self, IntPtr subscriber); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVReceiver_removeSubscriber(IntPtr self, IntPtr subscriber); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVReceiver_start(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVReceiver_stop(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool SVReceiver_isRunning(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVReceiver_destroy(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVReceiver_setInterfaceId(IntPtr self, string interfaceId); + + private IntPtr self; + + private bool isDisposed = false; + + /// + /// Initializes a new instance of the class. + /// + + public SVReceiver() + { + self = SVReceiver_create(); + } + + public void SetInterfaceId(string interfaceId) + { + SVReceiver_setInterfaceId(self, interfaceId); + } + + public void DisableDestAddrCheck() + { + SVReceiver_disableDestAddrCheck(self); + } + + public void EnableDestAddrCheck() + { + SVReceiver_enableDestAddrCheck(self); + } + + /// + /// Add a subscriber to handle + /// + /// Subscriber. + public void AddSubscriber(SVSubscriber subscriber) + { + SVReceiver_addSubscriber(self, subscriber.self); + } + + + public void RemoveSubscriber(SVSubscriber subscriber) + { + SVReceiver_removeSubscriber(self, subscriber.self); + } + + /// + /// Start handling SV messages + /// + public void Start() + { + SVReceiver_start(self); + } + + /// + /// Stop handling SV messges + /// + public void Stop() + { + SVReceiver_stop(self); + } + + public bool IsRunning() + { + return SVReceiver_isRunning(self); + } + + /// + /// Releases all resource used by the object. + /// + /// Call when you are finished using the . The + /// method leaves the in an unusable state. + /// After calling , you must release all references to the + /// so the garbage collector can reclaim the memory that the + /// was occupying. + public void Dispose() + { + if (isDisposed == false) + { + isDisposed = true; + SVReceiver_destroy(self); + self = IntPtr.Zero; + } + } + + ~SVReceiver() + { + Dispose(); + } + } + + + /// + /// SV listener. + /// + public delegate void SVUpdateListener(SVSubscriber report, object parameter, SVSubscriberASDU asdu); + + /// + /// Sampled Values (SV) Subscriber + /// + /// A subscriber is an instance associated with a single stream of measurement data. It is identified + /// by the Ethernet destination address, the appID value (both are on SV message level) and the svID value + /// that is part of each ASDU. + /// + public class SVSubscriber : IDisposable + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + 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); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr SVSubscriber_create(IntPtr ethAddr, UInt16 appID); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVSubscriber_setListener(IntPtr self, InternalSVUpdateListener listener, IntPtr parameter); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern void SVSubscriber_destroy(IntPtr self); + + internal IntPtr self; + + private bool isDisposed = false; + + private SVUpdateListener listener; + private object listenerParameter = null; + + private event InternalSVUpdateListener internalListener = null; + + private void internalSVUpdateListener(IntPtr subscriber, IntPtr parameter, IntPtr asdu) + { + try + { + + if (listener != null) + { + listener(this, listenerParameter, new SVSubscriberASDU(asdu)); + } + + } + catch (Exception e) + { + // older versions of mono 2.10 (for linux?) cause this exception + Console.WriteLine(e.Message); + } + } + + public SVSubscriber(byte[] ethAddr, UInt16 appID) + { + 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"); + + self = SVSubscriber_create(ethAddr, appID); + } + } + + public void SetListener(SVUpdateListener listener, object parameter) + { + this.listener = listener; + listenerParameter = parameter; + + if (internalListener == null) + { + internalListener = new InternalSVUpdateListener(internalSVUpdateListener); + + SVSubscriber_setListener(self, internalListener, IntPtr.Zero); + } + } + + public void Dispose() + { + if (isDisposed == false) + { + isDisposed = true; + SVSubscriber_destroy(self); + self = IntPtr.Zero; + } + } + } + + + public class SVSubscriberASDU + { + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt16 SVSubscriber_ASDU_getSmpCnt(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr SVSubscriber_ASDU_getSvId(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr SVSubscriber_ASDU_getDatSet(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt32 SVSubscriber_ASDU_getConfRev(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern byte SVSubscriber_ASDU_getSmpMod(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt16 SVSubscriber_ASDU_getSmpRate(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool SVSubscriber_ASDU_hasDatSet(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr SVSubscriber_ASDU_getDatSet(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt32 SVSubscriber_ASDU_getConfRev(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern byte SVSubscriber_ASDU_getSmpMod(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt16 SVSubscriber_ASDU_getSmpRate(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool SVSubscriber_ASDU_hasDatSet(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool SVSubscriber_ASDU_hasRefrTm(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool SVSubscriber_ASDU_hasRefrTm(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool SVSubscriber_ASDU_hasSmpMod(IntPtr self); - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool SVSubscriber_ASDU_hasSmpMod(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + private static extern bool SVSubscriber_ASDU_hasSmpRate(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt64 SVSubscriber_ASDU_getRefrTmAsMs(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern sbyte SVSubscriber_ASDU_getINT8(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern Int16 SVSubscriber_ASDU_getINT16(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern Int32 SVSubscriber_ASDU_getINT32(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern Int64 SVSubscriber_ASDU_getINT64(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern byte SVSubscriber_ASDU_getINT8U(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt16 SVSubscriber_ASDU_getINT16U(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt32 SVSubscriber_ASDU_getINT32U(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt64 SVSubscriber_ASDU_getINT64U(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern float SVSubscriber_ASDU_getFLOAT32(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern double SVSubscriber_ASDU_getFLOAT64(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt16 SVSubscriber_ASDU_getQuality(IntPtr self, int index); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern int SVSubscriber_ASDU_getDataSize(IntPtr self); + + private IntPtr self; + + internal SVSubscriberASDU(IntPtr self) + { + this.self = self; + } + + public UInt16 GetSmpCnt() + { + return SVSubscriber_ASDU_getSmpCnt(self); + } + + public string GetSvId() + { + return Marshal.PtrToStringAnsi(SVSubscriber_ASDU_getSvId(self)); + } + + public string GetDatSet() + { + return Marshal.PtrToStringAnsi(SVSubscriber_ASDU_getDatSet(self)); + } - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - [return: MarshalAs(UnmanagedType.I1)] - private static extern bool SVSubscriber_ASDU_hasSmpRate(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt64 SVSubscriber_ASDU_getRefrTmAsMs(IntPtr self); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern sbyte SVSubscriber_ASDU_getINT8(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern Int16 SVSubscriber_ASDU_getINT16(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern Int32 SVSubscriber_ASDU_getINT32(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern Int64 SVSubscriber_ASDU_getINT64(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern byte SVSubscriber_ASDU_getINT8U(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt16 SVSubscriber_ASDU_getINT16U(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt32 SVSubscriber_ASDU_getINT32U(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt64 SVSubscriber_ASDU_getINT64U(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern float SVSubscriber_ASDU_getFLOAT32(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern double SVSubscriber_ASDU_getFLOAT64(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern UInt16 SVSubscriber_ASDU_getQuality(IntPtr self, int index); - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern int SVSubscriber_ASDU_getDataSize(IntPtr self); - - private IntPtr self; - - internal SVSubscriberASDU (IntPtr self) - { - this.self = self; - } - - public UInt16 GetSmpCnt() - { - return SVSubscriber_ASDU_getSmpCnt (self); - } - - public string GetSvId() - { - return Marshal.PtrToStringAnsi (SVSubscriber_ASDU_getSvId(self)); - } - - public string GetDatSet() - { - return Marshal.PtrToStringAnsi (SVSubscriber_ASDU_getDatSet(self)); - } - - public UInt32 GetConfRev() - { - return SVSubscriber_ASDU_getConfRev (self); - } - - public SmpMod GetSmpMod() - { - return (SmpMod) SVSubscriber_ASDU_getSmpMod (self); - } + public UInt32 GetConfRev() + { + return SVSubscriber_ASDU_getConfRev(self); + } + + public SmpMod GetSmpMod() + { + return (SmpMod)SVSubscriber_ASDU_getSmpMod(self); + } - public UInt16 GetSmpRate() - { - return (UInt16)SVSubscriber_ASDU_getSmpRate (self); - } - - public bool HasDatSet() - { - return SVSubscriber_ASDU_hasDatSet (self); - } - - public bool HasRefrRm() - { - return SVSubscriber_ASDU_hasRefrTm (self); - } - - public bool HasSmpMod() - { - return SVSubscriber_ASDU_hasSmpMod (self); - } - - public bool HasSmpRate() - { - return SVSubscriber_ASDU_hasSmpRate (self); - } - - public UInt64 GetRefrTmAsMs() - { - return SVSubscriber_ASDU_getRefrTmAsMs (self); - } - - public sbyte GetINT8(int index) - { - return SVSubscriber_ASDU_getINT8 (self, index); - } - - public Int16 GetINT16(int index) - { - return SVSubscriber_ASDU_getINT16 (self, index); - } - - public Int32 GetINT32(int index) - { - return SVSubscriber_ASDU_getINT32 (self, index); - } - - public Int64 GetINT64(int index) - { - return SVSubscriber_ASDU_getINT64 (self, index); - } - - public byte GetINT8U(int index) - { - return SVSubscriber_ASDU_getINT8U (self, index); - } - - public UInt16 GetINT16U(int index) - { - return SVSubscriber_ASDU_getINT16U (self, index); - } - - public UInt32 GetINT32U(int index) - { - return SVSubscriber_ASDU_getINT32U (self, index); - } - - public UInt64 GetINT64U(int index) - { - return SVSubscriber_ASDU_getINT64U (self, index); - } - - public float GetFLOAT32(int index) - { - return SVSubscriber_ASDU_getFLOAT32 (self, index); - } - - public double GetFLOAT64(int index) - { - return SVSubscriber_ASDU_getFLOAT64 (self, index); - } - - private struct PTimestamp - { - [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = 8)] - public byte[] val; - } - - [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] - private static extern PTimestamp SVSubscriber_ASDU_getTimestamp(IntPtr self, int index); - - public Timestamp GetTimestamp(int index) - { - PTimestamp retVal = SVSubscriber_ASDU_getTimestamp (self, index); - - return new Timestamp (retVal.val); - } - - public Quality GetQuality(int index) - { - UInt16 qValue = SVSubscriber_ASDU_getQuality (self, index); - - return new Quality (qValue); - } - - /// - /// Gets the size of the payload data in bytes. The payload comprises the data set data. - /// - /// The payload data size in byte - public int GetDataSize() - { - return SVSubscriber_ASDU_getDataSize (self); - } - } - } - - } + public UInt16 GetSmpRate() + { + return SVSubscriber_ASDU_getSmpRate(self); + } + + public bool HasDatSet() + { + return SVSubscriber_ASDU_hasDatSet(self); + } + + public bool HasRefrRm() + { + return SVSubscriber_ASDU_hasRefrTm(self); + } + + public bool HasSmpMod() + { + return SVSubscriber_ASDU_hasSmpMod(self); + } + + public bool HasSmpRate() + { + return SVSubscriber_ASDU_hasSmpRate(self); + } + + public UInt64 GetRefrTmAsMs() + { + return SVSubscriber_ASDU_getRefrTmAsMs(self); + } + + public sbyte GetINT8(int index) + { + return SVSubscriber_ASDU_getINT8(self, index); + } + + public Int16 GetINT16(int index) + { + return SVSubscriber_ASDU_getINT16(self, index); + } + + public Int32 GetINT32(int index) + { + return SVSubscriber_ASDU_getINT32(self, index); + } + + public Int64 GetINT64(int index) + { + return SVSubscriber_ASDU_getINT64(self, index); + } + + public byte GetINT8U(int index) + { + return SVSubscriber_ASDU_getINT8U(self, index); + } + + public UInt16 GetINT16U(int index) + { + return SVSubscriber_ASDU_getINT16U(self, index); + } + + public UInt32 GetINT32U(int index) + { + return SVSubscriber_ASDU_getINT32U(self, index); + } + + public UInt64 GetINT64U(int index) + { + return SVSubscriber_ASDU_getINT64U(self, index); + } + + public float GetFLOAT32(int index) + { + return SVSubscriber_ASDU_getFLOAT32(self, index); + } + + public double GetFLOAT64(int index) + { + return SVSubscriber_ASDU_getFLOAT64(self, index); + } + + private struct PTimestamp + { + [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = 8)] + public byte[] val; + } + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern PTimestamp SVSubscriber_ASDU_getTimestamp(IntPtr self, int index); + + public Timestamp GetTimestamp(int index) + { + PTimestamp retVal = SVSubscriber_ASDU_getTimestamp(self, index); + + return new Timestamp(retVal.val); + } + + public Quality GetQuality(int index) + { + UInt16 qValue = SVSubscriber_ASDU_getQuality(self, index); + + return new Quality(qValue); + } + + /// + /// Gets the size of the payload data in bytes. The payload comprises the data set data. + /// + /// The payload data size in byte + public int GetDataSize() + { + return SVSubscriber_ASDU_getDataSize(self); + } + } + } + + } } diff --git a/dotnet/IEC61850forCSharp/TLS.cs b/dotnet/IEC61850forCSharp/TLS.cs index 0661f038..c692621e 100644 --- a/dotnet/IEC61850forCSharp/TLS.cs +++ b/dotnet/IEC61850forCSharp/TLS.cs @@ -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; /// /// 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) { diff --git a/dotnet/server_example_access_control/Program.cs b/dotnet/server_example_access_control/Program.cs index 2e6784e1..2aa0e287 100644 --- a/dotnet/server_example_access_control/Program.cs +++ b/dotnet/server_example_access_control/Program.cs @@ -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 passwords = parameter as List; + + 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 passwords = new List(); + passwords.Add("user1@testpw"); + passwords.Add("user2@testpw"); + + iedServer.SetAuthenticator(clientAuthenticator, passwords); + iedServer.Start(102); if (iedServer.IsRunning()) diff --git a/examples/iec61850_client_example5/client_example5.c b/examples/iec61850_client_example5/client_example5.c index e5bb22b7..e69d5350 100644 --- a/examples/iec61850_client_example5/client_example5.c +++ b/examples/iec61850_client_example5/client_example5.c @@ -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); diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c index bd3185d1..2a230c28 100644 --- a/src/iec61850/server/mms_mapping/reporting.c +++ b/src/iec61850/server/mms_mapping/reporting.c @@ -1,7 +1,7 @@ /* * reporting.c * - * Copyright 2013-2024 Michael Zillgith + * Copyright 2013-2025 Michael Zillgith * * This file is part of libIEC61850. * diff --git a/src/iec61850/server/model/config_file_parser.c b/src/iec61850/server/model/config_file_parser.c index e6b0b6b7..2e8acb3a 100644 --- a/src/iec61850/server/model/config_file_parser.c +++ b/src/iec61850/server/model/config_file_parser.c @@ -1,7 +1,7 @@ /* * config_file_parser.c * - * Copyright 2014-2024 Michael Zillgith + * Copyright 2014-2025 Michael Zillgith * * This file is part of libIEC61850. * diff --git a/src/mms/inc/iso_connection_parameters.h b/src/mms/inc/iso_connection_parameters.h index cc443daf..e2953c47 100644 --- a/src/mms/inc/iso_connection_parameters.h +++ b/src/mms/inc/iso_connection_parameters.h @@ -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 diff --git a/src/mms/iso_common/iso_connection_parameters.c b/src/mms/iso_common/iso_connection_parameters.c index 858def8d..ed9cd30e 100644 --- a/src/mms/iso_common/iso_connection_parameters.c +++ b/src/mms/iso_common/iso_connection_parameters.c @@ -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() { diff --git a/src/mms/iso_mms/server/mms_server.c b/src/mms/iso_mms/server/mms_server.c index 823e8542..a82627eb 100644 --- a/src/mms/iso_mms/server/mms_server.c +++ b/src/mms/iso_mms/server/mms_server.c @@ -1,7 +1,7 @@ /* * mms_server.c * - * Copyright 2013-2024 Michael Zillgith + * Copyright 2013-2025 Michael Zillgith * * This file is part of libIEC61850. *