diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
index d005c815..18afac22 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs
@@ -208,7 +208,7 @@ namespace IEC61850
return null;
}
- private ModelNode GetModelNodeFromNodeRef(IntPtr nodeRef)
+ internal ModelNode GetModelNodeFromNodeRef(IntPtr nodeRef)
{
ModelNode modelNode = null;
@@ -1248,12 +1248,28 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr DataSet_create(string name, IntPtr parent);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr DataSet_getName(IntPtr self);
+
public IntPtr self = IntPtr.Zero;
+ internal DataSet(IntPtr dataSetPtr)
+ {
+ self = dataSetPtr;
+ }
+
public DataSet(string name, LogicalNode parent)
{
self = DataSet_create(name, parent.self);
}
+
+ public string Name
+ {
+ get
+ {
+ return Marshal.PtrToStringAnsi(DataSet_getName(self));
+ }
+ }
}
public class DataSetEntry
@@ -1403,6 +1419,121 @@ namespace IEC61850
}
}
+ public class MmsGooseControlBlock
+ {
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr MmsGooseControlBlock_getName(IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr MmsGooseControlBlock_getLogicalNode(IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr MmsGooseControlBlock_getDataSet(IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ static extern bool MmsGooseControlBlock_getGoEna(IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern int MmsGooseControlBlock_getMinTime(IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern int MmsGooseControlBlock_getMaxTime(IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ static extern bool MmsGooseControlBlock_getFixedOffs(IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ static extern bool MmsGooseControlBlock_getNdsCom(IntPtr self);
+
+ private IntPtr self;
+ private LogicalNode ln = null;
+ private DataSet dataSet = null;
+
+ internal MmsGooseControlBlock(IntPtr self, IedModel iedModel)
+ {
+ this.self = self;
+
+ IntPtr lnPtr = MmsGooseControlBlock_getLogicalNode(self);
+
+ ModelNode lnModelNode = iedModel.GetModelNodeFromNodeRef(lnPtr);
+
+ if (lnModelNode != null && lnModelNode is LogicalNode)
+ {
+ this.ln = lnModelNode as LogicalNode;
+ }
+ }
+
+ public string Name
+ {
+ get
+ {
+ return Marshal.PtrToStringAnsi(MmsGooseControlBlock_getName(self));
+ }
+ }
+
+ public LogicalNode LN
+ {
+ get
+ {
+ return ln;
+ }
+ }
+
+ public DataSet DataSet
+ {
+ get
+ {
+ if (dataSet == null)
+ dataSet = new DataSet(MmsGooseControlBlock_getDataSet(self));
+
+ return dataSet;
+ }
+ }
+
+ public bool GoEna
+ {
+ get
+ {
+ return MmsGooseControlBlock_getGoEna(self);
+ }
+ }
+
+ public int MinTime
+ {
+ get
+ {
+ return MmsGooseControlBlock_getMinTime(self);
+ }
+ }
+
+ public int MaxTime
+ {
+ get
+ {
+ return MmsGooseControlBlock_getMaxTime(self);
+ }
+ }
+
+ public bool FixedOffs
+ {
+ get
+ {
+ return MmsGooseControlBlock_getFixedOffs(self);
+ }
+ }
+
+ public bool NdsCom
+ {
+ get
+ {
+ return MmsGooseControlBlock_getNdsCom(self);
+ }
+ }
+ }
+
///
/// Represents additional context information of the control action that caused the callback invokation
///
@@ -1554,6 +1685,8 @@ namespace IEC61850
}
}
+ public delegate void GoCBEventHandler(MmsGooseControlBlock goCB, int cbEvent, object parameter);
+
public delegate MmsDataAccessError WriteAccessHandler (DataAttribute dataAttr, MmsValue value,
ClientConnection connection, object parameter);
@@ -1759,6 +1892,27 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_setConnectionIndicationHandler(IntPtr self, InternalConnectionHandler handler, IntPtr parameter);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_enableGoosePublishing(IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_disableGoosePublishing(IntPtr self);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_setGooseInterfaceId(IntPtr self, string interfaceId);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_setGooseInterfaceIdEx(IntPtr self, IntPtr ln, string gcbName, string interfaceId);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_useGooseVlanTag(IntPtr self, IntPtr ln, string gcbName, [MarshalAs(UnmanagedType.I1)] bool useVlanTag);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate void InternalGoCBEventHandler(IntPtr goCB, int cbEvent, IntPtr parameter);
+
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServer_setGoCBHandler(IntPtr self, InternalGoCBEventHandler handler, IntPtr parameter);
+
private IntPtr self = IntPtr.Zero;
private InternalControlHandler internalControlHandlerRef = null;
@@ -2286,6 +2440,112 @@ namespace IEC61850
else
return null;
}
+
+ ///
+ /// Enable all GOOSE control blocks.
+ ///
+ /// This will set the GoEna attribute of all configured GOOSE control blocks
+ /// to true. If this method is not called at the startup or reset of the server
+ /// then configured GOOSE control blocks keep inactive until a MMS client enables
+ /// them by writing to the GOOSE control block.
+ public void EnableGoosePublishing()
+ {
+ IedServer_enableGoosePublishing(self);
+ }
+
+ ///
+ /// Disable all GOOSE control blocks.
+ ///
+ /// This will set the GoEna attribute of all configured GOOSE control blocks
+ /// to false. This will stop GOOSE transmission.
+ public void DisableGoosePublishing()
+ {
+ IedServer_disableGoosePublishing(self);
+ }
+
+ ///
+ /// Set the Ethernet interface to be used by GOOSE publishing
+ ///
+ ///
+ /// This function can be used to set the GOOSE interface ID. If not used or set to null the
+ /// default interface ID from stack_config.h is used.Note the interface ID is operating system
+ /// specific!
+ ///
+ /// the ID of the ethernet interface to be used for GOOSE publishing
+ public void SetGooseInterfaceId(string interfaceId)
+ {
+ IedServer_setGooseInterfaceId(self, interfaceId);
+ }
+
+ ///
+ /// Set the Ethernet interface to be used by GOOSE publishing
+ ///
+ ///
+ /// This function can be used to set the GOOSE interface ID for all GCBs (parameter ln = null) or for
+ /// a specific GCB specified by the logical node instance and the GCB name.
+ ///
+ /// ln the logical node that contains the GCB or null to set the ethernet interface ID for all GCBs
+ /// the name (not object reference!) of the GCB
+ /// the ID of the ethernet interface to be used for GOOSE publishing
+ public void SetGooseInterfaceId(LogicalNode ln, string gcbName, string interfaceId)
+ {
+ if (ln == null)
+ IedServer_setGooseInterfaceIdEx(self, IntPtr.Zero, gcbName, interfaceId);
+ else
+ IedServer_setGooseInterfaceIdEx(self, ln.self, gcbName, interfaceId);
+ }
+
+ ///
+ /// Enable/disable the use of VLAN tags in GOOSE messages
+ ///
+ ///
+ /// This function can be used to enable/disable VLAN tagging for all GCBs (parameter ln = null) or for
+ /// a specific GCB specified by the logical node instance and the GCB name.
+ ///
+ /// the logical node that contains the GCB or null to enable/disable VLAN tagging for all GCBs
+ /// the name (not object reference!) of the GCB
+ /// true to enable VLAN tagging, false otherwise
+ public void UseGooseVlanTag(LogicalNode ln, string gcbName, bool useVlanTag)
+ {
+ if (ln == null)
+ IedServer_useGooseVlanTag(self, IntPtr.Zero, gcbName, useVlanTag);
+ else
+ IedServer_useGooseVlanTag(self, ln.self, gcbName, useVlanTag);
+ }
+
+ private GoCBEventHandler goCbEventHandler = null;
+ private object goCbEventHandlerParameter = null;
+
+ private InternalGoCBEventHandler internalGoCBEventHandler = null;
+
+ private void InternalGoCBEventHandlerImplementation(IntPtr goCB, int cbEvent, IntPtr parameter)
+ {
+ if (goCbEventHandler != null)
+ {
+ MmsGooseControlBlock mmsGoCb = new MmsGooseControlBlock(goCB, iedModel);
+
+ goCbEventHandler.Invoke(mmsGoCb, cbEvent, goCbEventHandlerParameter);
+ }
+ }
+
+ ///
+ /// Set a callback handler for GoCB events (enabled/disabled)
+ ///
+ /// the callback handler
+ /// user provided parameter that is passed to the callback handler
+ public void SetGoCBHandler(GoCBEventHandler handler, object parameter)
+ {
+ goCbEventHandler = handler;
+ goCbEventHandlerParameter = parameter;
+
+ if (internalGoCBEventHandler == null)
+ {
+ internalGoCBEventHandler = new InternalGoCBEventHandler(InternalGoCBEventHandlerImplementation);
+
+ IedServer_setGoCBHandler(self, internalGoCBEventHandler, IntPtr.Zero);
+ }
+ }
+
}
}
diff --git a/dotnet/IEC61850forCSharp/IedServerConfig.cs b/dotnet/IEC61850forCSharp/IedServerConfig.cs
index 368dc894..9738f4ad 100644
--- a/dotnet/IEC61850forCSharp/IedServerConfig.cs
+++ b/dotnet/IEC61850forCSharp/IedServerConfig.cs
@@ -121,6 +121,9 @@ namespace IEC61850.Server
[return: MarshalAs(UnmanagedType.I1)]
static extern bool IedServerConfig_isOwnerForRCBEnabled(IntPtr self);
+ [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
+ static extern void IedServerConfig_useIntegratedGoosePublisher(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool enable);
+
internal IntPtr self;
public IedServerConfig()
@@ -336,6 +339,18 @@ namespace IEC61850.Server
}
}
+ ///
+ /// Enable/disable using the integrated GOOSE publisher for configured GoCBs
+ ///
+ /// true when integrated GOOSE publisher is used; otherwise, false. Defaults to true
+ public bool UseIntegratedGoosePublisher
+ {
+ set
+ {
+ IedServerConfig_useIntegratedGoosePublisher(self, value);
+ }
+ }
+
///
/// Releases all resource used by the object.
///
diff --git a/dotnet/dotnet.sln b/dotnet/dotnet.sln
index c2ab42d8..ba4aec17 100644
--- a/dotnet/dotnet.sln
+++ b/dotnet/dotnet.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
-VisualStudioVersion = 12.0.40629.0
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.779
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IEC61850.NET", "IEC61850forCSharp\IEC61850.NET.csproj", "{C35D624E-5506-4560-8074-1728F1FA1A4D}"
EndProject
@@ -48,94 +48,104 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_setting_grou
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_async", "client_example_async\client_example_async.csproj", "{71902641-776A-47D8-9C0E-9ACBBEAC1370}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "server_goose_publisher", "server_goose_publisher\server_goose_publisher.csproj", "{C14BB883-86B8-401C-B3D6-B655F55F3298}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Release|Any CPU.Build.0 = Release|Any CPU
- {0DA95476-B149-450B-AC36-01CEECFC1A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0DA95476-B149-450B-AC36-01CEECFC1A43}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0DA95476-B149-450B-AC36-01CEECFC1A43}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0DA95476-B149-450B-AC36-01CEECFC1A43}.Release|Any CPU.Build.0 = Release|Any CPU
- {1285372C-2E62-494A-A661-8D5D3873318C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1285372C-2E62-494A-A661-8D5D3873318C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1285372C-2E62-494A-A661-8D5D3873318C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1285372C-2E62-494A-A661-8D5D3873318C}.Release|Any CPU.Build.0 = Release|Any CPU
- {14C71267-2F38-460D-AA55-6803EE80AFB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {14C71267-2F38-460D-AA55-6803EE80AFB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {14C71267-2F38-460D-AA55-6803EE80AFB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {14C71267-2F38-460D-AA55-6803EE80AFB4}.Release|Any CPU.Build.0 = Release|Any CPU
- {2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Release|Any CPU.Build.0 = Release|Any CPU
- {44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C35D624E-5506-4560-8074-1728F1FA1A4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C35D624E-5506-4560-8074-1728F1FA1A4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C35D624E-5506-4560-8074-1728F1FA1A4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C35D624E-5506-4560-8074-1728F1FA1A4D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C616A6DF-831E-443C-9310-3F343A6E3D1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C616A6DF-831E-443C-9310-3F343A6E3D1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C616A6DF-831E-443C-9310-3F343A6E3D1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C616A6DF-831E-443C-9310-3F343A6E3D1A}.Release|Any CPU.Build.0 = Release|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59B85486-F48D-4978-BD35-8F5C3A8288D4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C351CFA4-E54E-49A1-86CE-69643535541A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C351CFA4-E54E-49A1-86CE-69643535541A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2A226B6D-1D1F-4BFE-B8CC-158116F71270}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0BECEC77-2315-4B95-AFF9-E6007E644BBF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Release|Any CPU.Build.0 = Release|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}.Release|Any CPU.Build.0 = Release|Any CPU
- {6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Release|Any CPU.Build.0 = Release|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{71485F99-2976-45E6-B73D-4946E594C15C}.Release|Any CPU.Build.0 = Release|Any CPU
- {71902641-776A-47D8-9C0E-9ACBBEAC1370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {71902641-776A-47D8-9C0E-9ACBBEAC1370}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {71902641-776A-47D8-9C0E-9ACBBEAC1370}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {71902641-776A-47D8-9C0E-9ACBBEAC1370}.Release|Any CPU.Build.0 = Release|Any CPU
- {77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {77127456-19B9-4D1A-AEF9-40F8D1C5695E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {14C71267-2F38-460D-AA55-6803EE80AFB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {14C71267-2F38-460D-AA55-6803EE80AFB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {14C71267-2F38-460D-AA55-6803EE80AFB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {14C71267-2F38-460D-AA55-6803EE80AFB4}.Release|Any CPU.Build.0 = Release|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}.Release|Any CPU.Build.0 = Release|Any CPU
- {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1285372C-2E62-494A-A661-8D5D3873318C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1285372C-2E62-494A-A661-8D5D3873318C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1285372C-2E62-494A-A661-8D5D3873318C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1285372C-2E62-494A-A661-8D5D3873318C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {44651D2D-3252-4FD5-8B8B-5552DBE1B499}.Release|Any CPU.Build.0 = Release|Any CPU
{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}.Release|Any CPU.Build.0 = Release|Any CPU
- {C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C351CFA4-E54E-49A1-86CE-69643535541A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C351CFA4-E54E-49A1-86CE-69643535541A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C351CFA4-E54E-49A1-86CE-69643535541A}.Release|Any CPU.Build.0 = Release|Any CPU
- {C35D624E-5506-4560-8074-1728F1FA1A4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C35D624E-5506-4560-8074-1728F1FA1A4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C35D624E-5506-4560-8074-1728F1FA1A4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C35D624E-5506-4560-8074-1728F1FA1A4D}.Release|Any CPU.Build.0 = Release|Any CPU
- {C616A6DF-831E-443C-9310-3F343A6E3D1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C616A6DF-831E-443C-9310-3F343A6E3D1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C616A6DF-831E-443C-9310-3F343A6E3D1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C616A6DF-831E-443C-9310-3F343A6E3D1A}.Release|Any CPU.Build.0 = Release|Any CPU
- {D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}.Release|Any CPU.Build.0 = Release|Any CPU
- {FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {FBDFE530-DBEB-474B-BA54-9AB287DD57B3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0DA95476-B149-450B-AC36-01CEECFC1A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0DA95476-B149-450B-AC36-01CEECFC1A43}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0DA95476-B149-450B-AC36-01CEECFC1A43}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0DA95476-B149-450B-AC36-01CEECFC1A43}.Release|Any CPU.Build.0 = Release|Any CPU
+ {71902641-776A-47D8-9C0E-9ACBBEAC1370}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {71902641-776A-47D8-9C0E-9ACBBEAC1370}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {71902641-776A-47D8-9C0E-9ACBBEAC1370}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {71902641-776A-47D8-9C0E-9ACBBEAC1370}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C14BB883-86B8-401C-B3D6-B655F55F3298}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C14BB883-86B8-401C-B3D6-B655F55F3298}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C14BB883-86B8-401C-B3D6-B655F55F3298}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C14BB883-86B8-401C-B3D6-B655F55F3298}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {9F590B86-C80C-4658-83BC-855A87751CEF}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
Policies = $0
@@ -149,7 +159,4 @@ Global
$2.inheritsScope = text/plain
StartupItem = IEC61850forCSharp\IEC61850forCSharp.csproj
EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
EndGlobal
diff --git a/dotnet/server1/server1.csproj b/dotnet/server1/server1.csproj
index d1c45eeb..ab6d9c85 100644
--- a/dotnet/server1/server1.csproj
+++ b/dotnet/server1/server1.csproj
@@ -48,4 +48,4 @@
PreserveNewest
-
+
\ No newline at end of file
diff --git a/dotnet/server_goose_publisher/App.config b/dotnet/server_goose_publisher/App.config
new file mode 100644
index 00000000..731f6de6
--- /dev/null
+++ b/dotnet/server_goose_publisher/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/server_goose_publisher/Properties/AssemblyInfo.cs b/dotnet/server_goose_publisher/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..181aecad
--- /dev/null
+++ b/dotnet/server_goose_publisher/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("server_goose_publisher")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("server_goose_publisher")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c14bb883-86b8-401c-b3d6-b655f55f3298")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/dotnet/server_goose_publisher/ServerExampleWithGoosePublisher.cs b/dotnet/server_goose_publisher/ServerExampleWithGoosePublisher.cs
new file mode 100644
index 00000000..4af291da
--- /dev/null
+++ b/dotnet/server_goose_publisher/ServerExampleWithGoosePublisher.cs
@@ -0,0 +1,129 @@
+using System;
+using IEC61850.Server;
+using IEC61850.Common;
+using System.Threading;
+
+namespace server_goose_publisher
+{
+ ///
+ /// This example shows how to use the server integrated GOOSE publisher from .NET
+ ///
+ ///
+ /// This example requires that the native library (libiec61850) is compiled with GOOSE support.
+ ///
+ class ServerExampleWithGoosePublisher
+ {
+ public static void Main(string[] args)
+ {
+ bool running = true;
+
+ /* run until Ctrl-C is pressed */
+ Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e)
+ {
+ e.Cancel = true;
+ running = false;
+ };
+
+ IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("simpleIO_direct_control_goose.cfg");
+
+ if (iedModel == null)
+ {
+ Console.WriteLine("No valid data model found!");
+ return;
+ }
+
+ iedModel.SetIedName("TestIED");
+
+ DataObject spcso1 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO1");
+
+ IedServerConfig config = new IedServerConfig();
+ config.ReportBufferSize = 100000;
+
+ IedServer iedServer = new IedServer(iedModel, config);
+
+ // Set GOOSE interface (e.g. "eth0" for Linux or "0" for Windows (first interface)
+ iedServer.SetGooseInterfaceId("0");
+
+ // The GoCBEventHandler can be used to track GoCB events
+ iedServer.SetGoCBHandler(delegate (MmsGooseControlBlock goCB, int cbEvent, object parameter)
+ {
+ if (cbEvent == 1)
+ {
+ Console.WriteLine("GCB " + goCB.LN.GetName() + ":" + goCB.Name + " enabled");
+ }
+ else
+ {
+ Console.WriteLine("GCB " + goCB.LN.GetName() + ":" + goCB.Name + " disabled");
+ }
+ }, null);
+
+ iedServer.SetCheckHandler(spcso1, delegate (ControlAction action, object parameter, MmsValue ctlVal, bool test, bool interlockCheck)
+ {
+
+ Console.WriteLine("Received binary control command:");
+ Console.WriteLine(" ctlNum: " + action.GetCtlNum());
+ Console.WriteLine(" execution-time: " + action.GetControlTimeAsDataTimeOffset().ToString());
+
+ return CheckHandlerResult.ACCEPTED;
+ }, null);
+
+ iedServer.SetControlHandler(spcso1, delegate (ControlAction action, object parameter, MmsValue ctlVal, bool test)
+ {
+ bool val = ctlVal.GetBoolean();
+
+ if (val)
+ Console.WriteLine("execute binary control command: on");
+ else
+ Console.WriteLine("execute binary control command: off");
+
+ return ControlHandlerResult.OK;
+ }, null);
+
+ DataObject spcso2 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO2");
+
+ iedServer.SetSelectStateChangedHandler(spcso2, delegate (ControlAction action, object parameter, bool isSelected, SelectStateChangedReason reason)
+ {
+ DataObject cObj = action.GetControlObject();
+
+ Console.WriteLine("Control object " + cObj.GetObjectReference() + (isSelected ? " selected" : " unselected") + " reason: " + reason.ToString());
+
+ }, null);
+
+ iedServer.Start(102);
+
+ // Enable GOOSE publishing for all GOOSE control blocks
+ iedServer.EnableGoosePublishing();
+
+ if (iedServer.IsRunning())
+ {
+ Console.WriteLine("Server started");
+
+ GC.Collect();
+
+ DataObject ggio1AnIn1 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.AnIn1");
+
+ DataAttribute ggio1AnIn1magF = (DataAttribute)ggio1AnIn1.GetChild("mag.f");
+ DataAttribute ggio1AnIn1T = (DataAttribute)ggio1AnIn1.GetChild("t");
+
+ float floatVal = 1.0f;
+
+ while (running)
+ {
+ floatVal += 1f;
+ iedServer.UpdateTimestampAttributeValue(ggio1AnIn1T, new Timestamp(DateTime.Now));
+ iedServer.UpdateFloatAttributeValue(ggio1AnIn1magF, floatVal);
+ Thread.Sleep(100);
+ }
+
+ iedServer.Stop();
+ Console.WriteLine("Server stopped");
+ }
+ else
+ {
+ Console.WriteLine("Failed to start server");
+ }
+
+ iedServer.Destroy();
+ }
+ }
+}
diff --git a/dotnet/server_goose_publisher/server_goose_publisher.csproj b/dotnet/server_goose_publisher/server_goose_publisher.csproj
new file mode 100644
index 00000000..5cf3a856
--- /dev/null
+++ b/dotnet/server_goose_publisher/server_goose_publisher.csproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {C14BB883-86B8-401C-B3D6-B655F55F3298}
+ Exe
+ server_goose_publisher
+ server_goose_publisher
+ v4.6.1
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+ {c35d624e-5506-4560-8074-1728f1fa1a4d}
+ IEC61850.NET
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/server_goose_publisher/simpleIO_direct_control_goose.cfg b/dotnet/server_goose_publisher/simpleIO_direct_control_goose.cfg
new file mode 100644
index 00000000..1ebb7159
--- /dev/null
+++ b/dotnet/server_goose_publisher/simpleIO_direct_control_goose.cfg
@@ -0,0 +1,217 @@
+MODEL(simpleIO){
+LD(GenericIO){
+LN(LLN0){
+DO(Mod 0){
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+DA(ctlModel 0 12 4 0 0)=0;
+}
+DO(Beh 0){
+DA(stVal 0 3 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+DO(Health 0){
+DA(stVal 0 3 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+DO(NamPlt 0){
+DA(vendor 0 20 5 0 0);
+DA(swRev 0 20 5 0 0);
+DA(d 0 20 5 0 0);
+DA(configRev 0 20 5 0 0);
+DA(ldNs 0 20 11 0 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(Events3){
+DE(GGIO1$ST$SPCSO1$stVal);
+DE(GGIO1$ST$SPCSO1$q);
+DE(GGIO1$ST$SPCSO2$stVal);
+DE(GGIO1$ST$SPCSO2$q);
+DE(GGIO1$ST$SPCSO3$stVal);
+DE(GGIO1$ST$SPCSO3$q);
+DE(GGIO1$ST$SPCSO4$stVal);
+DE(GGIO1$ST$SPCSO4$q);
+}
+DS(AnalogValues){
+DE(GGIO1$MX$AnIn1);
+DE(GGIO1$MX$AnIn2);
+DE(GGIO1$MX$AnIn3);
+DE(GGIO1$MX$AnIn4);
+}
+RC(EventsRCB01 Events 0 Events 1 24 175 50 1000);
+RC(AnalogValuesRCB01 AnalogValues 0 AnalogValues 1 24 175 50 1000);
+GC(gcbEvents events Events3 2 0 1000 3000 ){
+PA(4 1 4096 010ccd010001);
+}
+GC(gcbAnalogValues analog AnalogValues 2 0 -1 -1 ){
+PA(4 1 4096 010ccd010001);
+}
+}
+LN(LPHD1){
+DO(PhyNam 0){
+DA(vendor 0 20 5 0 0);
+}
+DO(PhyHealth 0){
+DA(stVal 0 3 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+DO(Proxy 0){
+DA(stVal 0 0 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+}
+LN(GGIO1){
+DO(Mod 0){
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+DA(ctlModel 0 12 4 0 0)=0;
+}
+DO(Beh 0){
+DA(stVal 0 3 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+DO(Health 0){
+DA(stVal 0 3 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+DO(NamPlt 0){
+DA(vendor 0 20 5 0 0);
+DA(swRev 0 20 5 0 0);
+DA(d 0 20 5 0 0);
+}
+DO(AnIn1 0){
+DA(mag 0 27 1 1 0){
+DA(f 0 10 1 1 0);
+}
+DA(q 0 23 1 2 0);
+DA(t 0 22 1 0 0);
+}
+DO(AnIn2 0){
+DA(mag 0 27 1 1 0){
+DA(f 0 10 1 1 0);
+}
+DA(q 0 23 1 2 0);
+DA(t 0 22 1 0 0);
+}
+DO(AnIn3 0){
+DA(mag 0 27 1 1 0){
+DA(f 0 10 1 1 0);
+}
+DA(q 0 23 1 2 0);
+DA(t 0 22 1 0 0);
+}
+DO(AnIn4 0){
+DA(mag 0 27 1 1 0){
+DA(f 0 10 1 1 0);
+}
+DA(q 0 23 1 2 0);
+DA(t 0 22 1 0 0);
+}
+DO(SPCSO1 0){
+DA(stVal 0 0 0 1 0);
+DA(q 0 23 0 2 0);
+DA(Oper 0 27 12 0 0){
+DA(ctlVal 0 0 12 0 0);
+DA(origin 0 27 12 0 0){
+DA(orCat 0 12 12 0 0);
+DA(orIdent 0 13 12 0 0);
+}
+DA(ctlNum 0 6 12 0 0);
+DA(T 0 22 12 0 0);
+DA(Test 0 0 12 0 0);
+DA(Check 0 24 12 0 0);
+}
+DA(ctlModel 0 12 4 0 0)=1;
+DA(t 0 22 0 0 0);
+}
+DO(SPCSO2 0){
+DA(stVal 0 0 0 1 0);
+DA(q 0 23 0 2 0);
+DA(Oper 0 27 12 0 0){
+DA(ctlVal 0 0 12 0 0);
+DA(origin 0 27 12 0 0){
+DA(orCat 0 12 12 0 0);
+DA(orIdent 0 13 12 0 0);
+}
+DA(ctlNum 0 6 12 0 0);
+DA(T 0 22 12 0 0);
+DA(Test 0 0 12 0 0);
+DA(Check 0 24 12 0 0);
+}
+DA(ctlModel 0 12 4 0 0)=1;
+DA(t 0 22 0 0 0);
+}
+DO(SPCSO3 0){
+DA(stVal 0 0 0 1 0);
+DA(q 0 23 0 2 0);
+DA(Oper 0 27 12 0 0){
+DA(ctlVal 0 0 12 0 0);
+DA(origin 0 27 12 0 0){
+DA(orCat 0 12 12 0 0);
+DA(orIdent 0 13 12 0 0);
+}
+DA(ctlNum 0 6 12 0 0);
+DA(T 0 22 12 0 0);
+DA(Test 0 0 12 0 0);
+DA(Check 0 24 12 0 0);
+}
+DA(ctlModel 0 12 4 0 0)=1;
+DA(t 0 22 0 0 0);
+}
+DO(SPCSO4 0){
+DA(stVal 0 0 0 1 0);
+DA(q 0 23 0 2 0);
+DA(Oper 0 27 12 0 0){
+DA(ctlVal 0 0 12 0 0);
+DA(origin 0 27 12 0 0){
+DA(orCat 0 12 12 0 0);
+DA(orIdent 0 13 12 0 0);
+}
+DA(ctlNum 0 6 12 0 0);
+DA(T 0 22 12 0 0);
+DA(Test 0 0 12 0 0);
+DA(Check 0 24 12 0 0);
+}
+DA(ctlModel 0 12 4 0 0)=1;
+DA(t 0 22 0 0 0);
+}
+DO(Ind1 0){
+DA(stVal 0 0 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+DO(Ind2 0){
+DA(stVal 0 0 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+DO(Ind3 0){
+DA(stVal 0 0 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+DO(Ind4 0){
+DA(stVal 0 0 0 1 0);
+DA(q 0 23 0 2 0);
+DA(t 0 22 0 0 0);
+}
+}
+}
+}
diff --git a/dotnet/server_goose_publisher/simpleIO_direct_control_goose.cid b/dotnet/server_goose_publisher/simpleIO_direct_control_goose.cid
new file mode 100644
index 00000000..e25303f7
--- /dev/null
+++ b/dotnet/server_goose_publisher/simpleIO_direct_control_goose.cid
@@ -0,0 +1,275 @@
+
+
+
+
+
+
+
+ 10.0.0.2
+ 255.255.255.0
+ 10.0.0.1
+ 0001
+ 00000001
+ 0001
+
+
+
+ 1
+ 4
+ 01-0c-cd-01-00-01
+ 1000
+
+ 1000
+ 3000
+
+
+
+ 1
+ 4
+ 01-0c-cd-01-00-01
+ 1000
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status-only
+
+
+
+
+
+
+
+ status-only
+
+
+
+
+ direct-with-normal-security
+
+
+
+
+ direct-with-normal-security
+
+
+
+
+ direct-with-normal-security
+
+
+
+
+ direct-with-normal-security
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ status-only
+ direct-with-normal-security
+ sbo-with-normal-security
+ direct-with-enhanced-security
+ sbo-with-enhanced-security
+
+
+ not-supported
+ bay-control
+ station-control
+ remote-control
+ automatic-bay
+ automatic-station
+ automatic-remote
+ maintenance
+ process
+
+
+
diff --git a/src/iec61850/inc/iec61850_dynamic_model.h b/src/iec61850/inc/iec61850_dynamic_model.h
index e28ac506..4138d13c 100644
--- a/src/iec61850/inc/iec61850_dynamic_model.h
+++ b/src/iec61850/inc/iec61850_dynamic_model.h
@@ -329,6 +329,16 @@ PhyComAddress_create(uint8_t vlanPriority, uint16_t vlanId, uint16_t appId, uint
LIB61850_API DataSet*
DataSet_create(const char* name, LogicalNode* parent);
+/**
+ * \brief Get the name of the data set
+ *
+ * \param self the instance of the data set
+ *
+ * \returns the name of the data set (not the object reference).
+ */
+LIB61850_API const char*
+DataSet_getName(DataSet* self);
+
/**
* \brief returns the number of elements (entries) of the data set
*
diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h
index 3f503cba..e69f2c0e 100644
--- a/src/iec61850/inc/iec61850_server.h
+++ b/src/iec61850/inc/iec61850_server.h
@@ -637,7 +637,7 @@ IedServer_setGooseInterfaceId(IedServer self, const char* interfaceId);
* Note: This function has no effect when CONFIG_INCLUDE_GOOSE_SUPPORT is not set.
*
* \param self the instance of IedServer to operate on.
- * \param ln the logical node that contains the GCB or NULL to enable/disable VLAN tagging for all GCBs
+ * \param ln the logical node that contains the GCB or NULL to set the ethernet interface ID for all GCBs
* \param gcbName the name (not object reference!) of the GCB
* \param interfaceId the ID of the ethernet interface to be used for GOOSE publishing
*/
@@ -1584,6 +1584,16 @@ typedef struct sMmsGooseControlBlock* MmsGooseControlBlock;
typedef void (*GoCBEventHandler) (MmsGooseControlBlock goCb, int event, void* parameter);
+/**
+ * \brief Set a callback handler for GoCB events (enabled/disabled)
+ *
+ * The callback handler is called whenever a GOOSE control block is enabled or disabled.
+ * It can be used to integrate the external GOOSE publisher with the IEC 61850/MMS server.
+ *
+ * \param self the instance of IedServer to operate on.
+ * \param handler the callback handler
+ * \param parameter user provided parameter that is passed to the callback handler
+ */
LIB61850_API void
IedServer_setGoCBHandler(IedServer self, GoCBEventHandler handler, void* parameter);
diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c
index aee8a908..b89898fc 100644
--- a/src/iec61850/server/mms_mapping/mms_mapping.c
+++ b/src/iec61850/server/mms_mapping/mms_mapping.c
@@ -2294,7 +2294,7 @@ writeAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variable
MmsGooseControlBlock_disable(mmsGCB, self);
if (self->goCbHandler)
- self->goCbHandler(mmsGCB, IEC61850_GOCB_EVENT_ENABLE, self->goCbHandlerParameter);
+ self->goCbHandler(mmsGCB, IEC61850_GOCB_EVENT_DISABLE, self->goCbHandlerParameter);
}
return DATA_ACCESS_ERROR_SUCCESS;
diff --git a/src/iec61850/server/model/dynamic_model.c b/src/iec61850/server/model/dynamic_model.c
index 56ad9658..b8e9816b 100644
--- a/src/iec61850/server/model/dynamic_model.c
+++ b/src/iec61850/server/model/dynamic_model.c
@@ -654,6 +654,12 @@ DataSet_create(const char* name, LogicalNode* parent)
return self;
}
+const char*
+DataSet_getName(DataSet* self)
+{
+ return self->name;
+}
+
int
DataSet_getSize(DataSet* self)
{