diff --git a/dotnet/IEC61850forCSharp/IEC61850Model/SVControlBlock.cs b/dotnet/IEC61850forCSharp/IEC61850Model/SVControlBlock.cs
new file mode 100644
index 00000000..b1dce114
--- /dev/null
+++ b/dotnet/IEC61850forCSharp/IEC61850Model/SVControlBlock.cs
@@ -0,0 +1,57 @@
+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
+{
+ // IEC 61850 server API.
+ namespace Model
+ {
+ public enum SMVEvent
+ {
+ IEC61850_SVCB_EVENT_ENABLE = 1,
+ IEC61850_SVCB_EVENT_DISABLE = 0,
+ }
+
+ public class SVControlBlock : ModelNode
+ {
+ private IntPtr self = IntPtr.Zero;
+ public IedModel parent { get; }
+ 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,
+ UInt16 smpRate, uint optFlds, bool isUnicast);
+
+ ///
+ /// create a new Multicast/Unicast Sampled Value (SV) control block (SvCB)
+ /// Create a new Sampled Value control block(SvCB) and add it to the given logical node(LN)
+ ///
+ /// name of the SvCB relative to the parent LN
+ /// the parent LN
+ /// the application ID of the SvCB
+ /// the data set reference to be used by the SVCB
+ /// the configuration revision
+ /// the sampling mode used
+ /// the sampling rate used
+ ///
+ /// the optional element configuration
+ 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);
+ this.parent = parent;
+ }
+
+ public SVControlBlock(IntPtr self)
+ {
+ this.self = self;
+ }
+
+ }
+ }
+
+}
diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
index 98779da5..e971c547 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
@@ -30,6 +30,7 @@ using System.Security.Cryptography;
using System.Xml.Linq;
using IEC61850.Client;
using IEC61850.Common;
+using IEC61850.Model;
using IEC61850.TLS;
using static System.Collections.Specialized.BitVector32;
using static System.Net.Mime.MediaTypeNames;
@@ -86,6 +87,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedModel_getDeviceByInst(IntPtr self, string ldInst);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr IedModel_getSVControlBlock(IntPtr self, IntPtr parentLN, string svcbName);
+
internal IntPtr self = IntPtr.Zero;
internal IedModel(IntPtr self)
@@ -306,6 +310,16 @@ namespace IEC61850
return GetModelNodeFromNodeRef (nodeRef);
}
+ public SVControlBlock GetSVControlBlock(LogicalNode logicalNode, string svcbName)
+ {
+ IntPtr nodeRef = IedModel_getSVControlBlock(self, logicalNode.self, svcbName);
+
+ if (nodeRef == IntPtr.Zero)
+ return null;
+
+ return new SVControlBlock(nodeRef);
+ }
+
}
///
@@ -2497,8 +2511,8 @@ namespace IEC61850
///// the SVCB control block instance
///// the event handler to be used
///// user provided parameter that is passed to the handler
- //[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
- //public static extern void IedServer_setSVCBHandler(IntPtr self, IntPtr svcb, SVCBEventHandler handler, IntPtr parameter);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void IedServer_setSVCBHandler(IntPtr self, IntPtr svcb, SVCBEventHandler handler, IntPtr parameter);
/////
///// callback handler for SVCB events
@@ -2506,8 +2520,8 @@ namespace IEC61850
///// the related SVCB instance
///// event type
///// user defined parameter
- //[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- //public delegate void SVCBEventHandler(IntPtr svcb, int eventType, IntPtr parameter);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void SVCBEventHandler(IntPtr svcb, int eventType, IntPtr parameter);
///
/// callback handler to control client read access to data attributes
@@ -3015,79 +3029,74 @@ namespace IEC61850
//------------
- //public delegate bool InternalSVCBEventHandler(SampledValuesControlBlock sampledValuesControlBlock, SMVEvent sMVEvent, object parameter);
+ public delegate void InternalSVCBEventHandler(SVControlBlock sampledValuesControlBlock, SMVEvent sMVEvent, object parameter);
- //private InternalSVCBEventHandler internalSVCBEventHandler = null;
+ private InternalSVCBEventHandler internalSVCBEventHandler = null;
- //private object sVCBEventHandlerParameter = null;
+ private object sVCBEventHandlerParameter = null;
- //private SVCBEventHandler sVCBEventHandler = null;
+ private SVCBEventHandler sVCBEventHandler = null;
- //internal class SVCHandlerInfo
- //{
- // public SampledValuesControlBlock sampledValuesControlBlock = null;
- // public GCHandle handle;
+ internal class SVCHandlerInfo
+ {
+ public SVControlBlock sampledValuesControlBlock = null;
+ public GCHandle handle;
- // public InternalSVCBEventHandler internalSVCBEventHandler = null;
- // public object svcHandlerParameter = null;
+ public InternalSVCBEventHandler internalSVCBEventHandler = null;
+ public object svcHandlerParameter = null;
- // public SVCHandlerInfo(SampledValuesControlBlock sampledValuesControlBlock)
- // {
- // this.sampledValuesControlBlock = sampledValuesControlBlock;
- // this.handle = GCHandle.Alloc(this);
- // }
+ public SVCHandlerInfo(SVControlBlock sampledValuesControlBlock)
+ {
+ this.sampledValuesControlBlock = sampledValuesControlBlock;
+ this.handle = GCHandle.Alloc(this);
+ }
- // ~SVCHandlerInfo()
- // {
- // this.handle.Free();
- // }
- //}
+ ~SVCHandlerInfo()
+ {
+ this.handle.Free();
+ }
+ }
- //private Dictionary svcHandlers = new Dictionary();
+ private Dictionary svcHandlers = new Dictionary();
- //private SVCHandlerInfo GetSVCHandlerInfo(SampledValuesControlBlock sampledValuesControlBlock)
- //{
- // SVCHandlerInfo info;
+ private SVCHandlerInfo GetSVCHandlerInfo(SVControlBlock sampledValuesControlBlock)
+ {
+ SVCHandlerInfo info;
- // svcHandlers.TryGetValue(sampledValuesControlBlock, out info);
+ svcHandlers.TryGetValue(sampledValuesControlBlock, out info);
- // if (info == null)
- // {
- // info = new SVCHandlerInfo(sampledValuesControlBlock);
- // svcHandlers.Add(sampledValuesControlBlock, info);
- // }
+ if (info == null)
+ {
+ info = new SVCHandlerInfo(sampledValuesControlBlock);
+ svcHandlers.Add(sampledValuesControlBlock, info);
+ }
- // return info;
- //}
+ return info;
+ }
- //public void SetSVCBHandler(InternalSVCBEventHandler handler, SampledValuesControlBlock sampledValuesControlBlock, object parameter)
- //{
- // SVCHandlerInfo info = GetSVCHandlerInfo(sampledValuesControlBlock);
+ public void SetSVCBHandler(InternalSVCBEventHandler handler, SVControlBlock sampledValuesControlBlock, object parameter)
+ {
+ SVCHandlerInfo info = GetSVCHandlerInfo(sampledValuesControlBlock);
- // info.internalSVCBEventHandler = handler;
- // info.svcHandlerParameter = parameter;
+ info.internalSVCBEventHandler = handler;
+ info.svcHandlerParameter = parameter;
- // if (sVCBEventHandler == null)
- // sVCBEventHandler = new SVCBEventHandler(InternalSVCBEventHandlerImplementation);
+ if (sVCBEventHandler == null)
+ sVCBEventHandler = new SVCBEventHandler(InternalSVCBEventHandlerImplementation);
- // IedServer_setSVCBHandler(self, sampledValuesControlBlock.Self, sVCBEventHandler, GCHandle.ToIntPtr(info.handle));
- //}
+ IedServer_setSVCBHandler(self, sampledValuesControlBlock.Self, sVCBEventHandler, GCHandle.ToIntPtr(info.handle));
+ }
- //public enum SMVEvent
- //{
- // IEC61850_SVCB_EVENT_ENABLE = 1,
- // IEC61850_SVCB_EVENT_DISABLE = 0,
- //}
- //private void InternalSVCBEventHandlerImplementation(IntPtr svcb, int eventType, IntPtr parameter)
- //{
- // GCHandle handle = GCHandle.FromIntPtr(parameter);
+ private void InternalSVCBEventHandlerImplementation(IntPtr svcb, int eventType, IntPtr parameter)
+ {
+ GCHandle handle = GCHandle.FromIntPtr(parameter);
- // SVCHandlerInfo info = (SVCHandlerInfo)handle.Target;
+ SVCHandlerInfo info = (SVCHandlerInfo)handle.Target;
- // if (info != null && info.internalSVCBEventHandler != null)
- // info.internalSVCBEventHandler(info.sampledValuesControlBlock,(SMVEvent)eventType, info.svcHandlerParameter);
- //}
+ if (info != null && info.internalSVCBEventHandler != null)
+ info.internalSVCBEventHandler(info.sampledValuesControlBlock, (SMVEvent)eventType, info.svcHandlerParameter);
+ }
public delegate MmsDataAccessError InternalReadAccessHandler(LogicalDevice ld, LogicalNode ln, DataObject dataObject, FunctionalConstraint fc, ClientConnection connection, object parameter);
diff --git a/dotnet/server_example_access_control/Program.cs b/dotnet/server_example_access_control/Program.cs
index 630c437e..a936d0a2 100644
--- a/dotnet/server_example_access_control/Program.cs
+++ b/dotnet/server_example_access_control/Program.cs
@@ -15,6 +15,7 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using IEC61850.Client;
using ReportControlBlock = IEC61850.Server.ReportControlBlock;
+using IEC61850.Model;
namespace server_access_control
{
@@ -222,18 +223,16 @@ namespace server_access_control
/* Handler for Sampled values control block
*/
- //void sVCBEventHandler(SampledValuesControlBlock svcb, SMVEvent smvEvent, object parameter)
- //{
- // Console.WriteLine(svcb.GetNoASDU() + " event: "+ smvEvent.ToString() );
- //}
-
- //implement IedModel_getSVControlBlock && SVControlBlock
- //SampledValuesControlBlock sampledValuesControlBlock = (SampledValuesControlBlock)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO1");
-
+ void SVCBEventHandler(SVControlBlock svcb, SMVEvent smvEvent, object parameter)
+ {
+ Console.WriteLine("SVControlBlock event " + smvEvent.ToString());
+ }
- //iedServer.SetSVCBHandler(sVCBEventHandler,)
+ //LogicalNode logicalNode = (LogicalNode)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1");
+ //SVControlBlock sampledValuesControlBlock = iedModel.GetSVControlBlock(logicalNode, "MSVCB01");
+ //iedServer.SetSVCBHandler(SVCBEventHandler, sampledValuesControlBlock, null);
- //SettingGroups
+ /*SettingGroups*/
LogicalDevice logicalDevice = (LogicalDevice)iedModel.GetModelNodeByShortObjectReference("GenericIO"); ;
SettingGroupControlBlock settingGroupControlBlock = logicalDevice.GetSettingGroupControlBlock();
@@ -250,11 +249,11 @@ namespace server_access_control
DataAttribute dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.StrVal.setMag.f");
iedServer.UpdateFloatAttributeValue(dataAttribute, ptoc1Settings[actSG - 1].strVal);
- dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.opDlTmms.setVal");
+ dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.OpDlTmms.setVal");
iedServer.UpdateInt32AttributeValue(dataAttribute, ptoc1Settings[actSG - 1].opDlTmms);
- dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.rsDlTmms.setVal");
+ dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RsDlTmms.setVal");
iedServer.UpdateInt32AttributeValue(dataAttribute, ptoc1Settings[actSG - 1].rsDlTmms);
- dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.rstTms.setVal");
+ dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RstTms.setVal");
iedServer.UpdateInt32AttributeValue(dataAttribute, ptoc1Settings[actSG - 1].rstTms);
}
diff --git a/dotnet/server_example_access_control/model.cfg b/dotnet/server_example_access_control/model.cfg
index b3d21dc4..ad0b6472 100644
--- a/dotnet/server_example_access_control/model.cfg
+++ b/dotnet/server_example_access_control/model.cfg
@@ -1,81 +1,5 @@
MODEL(simpleIO){
LD(GenericIO){
-LN(LLN0){
-SG(1 5)
-DO(Mod 0){
-DA(stVal 0 12 0 17 0)=1;
-DA(q 0 23 0 18 0);
-DA(t 0 22 0 16 0);
-DA(ctlModel 0 12 4 16 0)=0;
-}
-DO(Beh 0){
-DA(stVal 0 12 0 17 0)=1;
-DA(q 0 23 0 18 0);
-DA(t 0 22 0 16 0);
-}
-DO(Health 0){
-DA(stVal 0 12 0 17 0)=1;
-DA(q 0 23 0 18 0);
-DA(t 0 22 0 16 0);
-}
-DO(NamPlt 0){
-DA(vendor 0 20 5 16 0)="MZ Automation";
-DA(swRev 0 20 5 16 0)="1.3.0";
-DA(d 0 20 5 16 0)="libiec61850 server example";
-DA(configRev 0 20 5 16 0);
-DA(ldNs 0 20 11 16 0);
-}
-DS(Events){
-DE(GGIO1$ST$SPCSO1$stVal);
-DE(GGIO1$ST$SPCSO2$stVal);
-DE(GGIO1$ST$SPCSO3$stVal);
-DE(GGIO1$ST$SPCSO4$stVal);
-}
-DS(Events2){
-DE(GGIO1$ST$SPCSO1);
-DE(GGIO1$ST$SPCSO2);
-DE(GGIO1$ST$SPCSO3);
-DE(GGIO1$ST$SPCSO4);
-}
-DS(Measurements){
-DE(GGIO1$MX$AnIn1$mag$f);
-DE(GGIO1$MX$AnIn1$q);
-DE(GGIO1$MX$AnIn2$mag$f);
-DE(GGIO1$MX$AnIn2$q);
-DE(GGIO1$MX$AnIn3$mag$f);
-DE(GGIO1$MX$AnIn3$q);
-DE(GGIO1$MX$AnIn4$mag$f);
-DE(GGIO1$MX$AnIn4$q);
-}
-DS(ServiceTracking){
-DE(LTRK1$SR$SpcTrk);
-DE(LTRK1$SR$DpcTrk);
-DE(LTRK1$SR$IncTrk);
-DE(LTRK1$SR$BscTrk);
-DE(LTRK1$SR$UrcbTrk);
-DE(LTRK1$SR$BrcbTrk);
-DE(LTRK1$SR$GocbTrk);
-DE(LTRK1$SR$SgcbTrk);
-DE(LTRK1$SR$LocbTrk);
-}
-RC(EventsRCB01 Events1 0 Events2 1 24 175 50 1000);
-RC(EventsIndexed01 Events2 0 Events 1 24 175 50 1000);
-RC(EventsIndexed02 Events2 0 Events 1 24 175 50 1000);
-RC(EventsIndexed03 Events2 0 Events 1 24 175 50 1000);
-RC(Measurements01 Measurements 1 Measurements 1 16 239 50 1000);
-RC(Measurements02 Measurements 1 Measurements 1 16 239 50 1000);
-RC(Measurements03 Measurements 1 Measurements 1 16 239 50 1000);
-RC(brcbServiceTracking01 ServiceTracking 1 ServiceTracking 1 19 228 0 0);
-RC(brcbServiceTracking02 ServiceTracking 1 ServiceTracking 1 19 228 0 0);
-RC(brcbServiceTracking03 ServiceTracking 1 ServiceTracking 1 19 228 0 0);
-LC(EventLog Events GenericIO/LLN0$EventLog 19 0 1 0);
-LC(GeneralLog - - 19 0 0 0);
-LOG();
-LOG(EventLog);
-GC(gcbEvents events Events 3 0 1000 3000){
-PA(4 1 1000 010CCD010001);
-}
-}
LN(LPHD1){
DO(PhyNam 0){
DA(vendor 0 20 5 16 0);
@@ -235,6 +159,85 @@ DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
}
+LN(LLN0){
+SG(1 5)
+DO(Mod 0){
+DA(stVal 0 12 0 17 0)=1;
+DA(q 0 23 0 18 0);
+DA(t 0 22 0 16 0);
+DA(ctlModel 0 12 4 16 0)=0;
+}
+DO(Beh 0){
+DA(stVal 0 12 0 17 0)=1;
+DA(q 0 23 0 18 0);
+DA(t 0 22 0 16 0);
+}
+DO(Health 0){
+DA(stVal 0 12 0 17 0)=1;
+DA(q 0 23 0 18 0);
+DA(t 0 22 0 16 0);
+}
+DO(NamPlt 0){
+DA(vendor 0 20 5 16 0)="MZ Automation";
+DA(swRev 0 20 5 16 0)="1.3.0";
+DA(d 0 20 5 16 0)="libiec61850 server example";
+DA(configRev 0 20 5 16 0);
+DA(ldNs 0 20 11 16 0);
+}
+DS(Events){
+DE(GGIO1$ST$SPCSO1$stVal);
+DE(GGIO1$ST$SPCSO2$stVal);
+DE(GGIO1$ST$SPCSO3$stVal);
+DE(GGIO1$ST$SPCSO4$stVal);
+}
+DS(Events2){
+DE(GGIO1$ST$SPCSO1);
+DE(GGIO1$ST$SPCSO2);
+DE(GGIO1$ST$SPCSO3);
+DE(GGIO1$ST$SPCSO4);
+}
+DS(Measurements){
+DE(GGIO1$MX$AnIn1$mag$f);
+DE(GGIO1$MX$AnIn1$q);
+DE(GGIO1$MX$AnIn2$mag$f);
+DE(GGIO1$MX$AnIn2$q);
+DE(GGIO1$MX$AnIn3$mag$f);
+DE(GGIO1$MX$AnIn3$q);
+DE(GGIO1$MX$AnIn4$mag$f);
+DE(GGIO1$MX$AnIn4$q);
+}
+DS(ServiceTracking){
+DE(LTRK1$SR$SpcTrk);
+DE(LTRK1$SR$DpcTrk);
+DE(LTRK1$SR$IncTrk);
+DE(LTRK1$SR$BscTrk);
+DE(LTRK1$SR$UrcbTrk);
+DE(LTRK1$SR$BrcbTrk);
+DE(LTRK1$SR$GocbTrk);
+DE(LTRK1$SR$SgcbTrk);
+DE(LTRK1$SR$LocbTrk);
+}
+RC(EventsRCB01 Events1 0 Events2 1 24 175 50 1000);
+RC(EventsIndexed01 Events2 0 Events 1 24 175 50 1000);
+RC(EventsIndexed02 Events2 0 Events 1 24 175 50 1000);
+RC(EventsIndexed03 Events2 0 Events 1 24 175 50 1000);
+RC(Measurements01 Measurements 1 Measurements 1 16 239 50 1000);
+RC(Measurements02 Measurements 1 Measurements 1 16 239 50 1000);
+RC(Measurements03 Measurements 1 Measurements 1 16 239 50 1000);
+RC(brcbServiceTracking01 ServiceTracking 1 ServiceTracking 1 19 228 0 0);
+RC(brcbServiceTracking02 ServiceTracking 1 ServiceTracking 1 19 228 0 0);
+RC(brcbServiceTracking03 ServiceTracking 1 ServiceTracking 1 19 228 0 0);
+LC(EventLog Events GenericIO/LLN0$EventLog 19 0 1 0);
+LC(GeneralLog - - 19 0 0 0);
+LOG();
+LOG(EventLog);
+GC(gcbEvents events Events 3 0 1000 3000){
+PA(4 1 1000 010CCD010001);
+}
+SMVC(MSVCB01 xxxxMUnn01 Events 0 0 0 1 0 ){
+PA(4 123 4000 010CCD040001);
+}
+}
LN(PTOC1){
DO(Mod 0){
DA(stVal 0 12 0 17 0);
diff --git a/dotnet/server_example_access_control/server_example_access_control.csproj b/dotnet/server_example_access_control/server_example_access_control.csproj
index c34022ad..618a553d 100644
--- a/dotnet/server_example_access_control/server_example_access_control.csproj
+++ b/dotnet/server_example_access_control/server_example_access_control.csproj
@@ -8,12 +8,12 @@
-
+
-
- PreserveNewest
+
+ Always
diff --git a/tools/model_generator_dotnet/Tools/Tools.csproj b/tools/model_generator_dotnet/Tools/Tools.csproj
index 09e31c57..10d47403 100644
--- a/tools/model_generator_dotnet/Tools/Tools.csproj
+++ b/tools/model_generator_dotnet/Tools/Tools.csproj
@@ -16,6 +16,7 @@
+
@@ -49,6 +50,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest