From bfa4631eea81c09fe6c8b5c6a7ca6ed2e3bbe483 Mon Sep 17 00:00:00 2001 From: Maxson Ramon dos Anjos Medeiros Date: Wed, 16 Jul 2025 17:49:13 +0200 Subject: [PATCH] =?UTF-8?q?->Add=20=C2=96GetChildWithFc=20on=20DataObject?= =?UTF-8?q?=20model,=20so=20we=20can=20get=20the=20DA=20fc=3DSE=20for=20th?= =?UTF-8?q?e=20SGCB=20handler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs | 26 ++++++++++++++++ .../server_example_access_control/Program.cs | 30 ++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs index 183df204..6d237e28 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs @@ -26,6 +26,7 @@ using System.Data; using System.Data.Common; using System.Diagnostics; using System.Runtime.InteropServices; +using System.Security.Cryptography; using System.Xml.Linq; using IEC61850.Client; using IEC61850.Common; @@ -927,6 +928,9 @@ 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); internal DataObject(IntPtr self, ModelNode parent) : base(self) { @@ -944,6 +948,28 @@ namespace IEC61850 self = DataObject_create (name, parent.self, arrayElements); } + /// + /// return a child model node with a given functional constraint + /// Sometimes the name is not enough to identify a model node.This is the case when + /// editable setting groups are used.In this case the setting group members have two different + /// model nodes associated that differ in their FC (SG and SE). + /// + /// the name of the child model node + /// the functional constraint of the model node + /// the model node instance or NULL if model node does not exist. + public DataAttribute GetChildWithFc(string objRef, FunctionalConstraint fc) + { + DataAttribute dataAttribute = null; + IntPtr da = ModelNode_getChildWithFc(this.self, objRef, (int)fc); + + if (da != IntPtr.Zero) + { + dataAttribute = new DataAttribute(da, this); + } + + return dataAttribute; + } + } public class DataAttribute : ModelNode diff --git a/dotnet/server_example_access_control/Program.cs b/dotnet/server_example_access_control/Program.cs index 9b4a3c5a..7a01724f 100644 --- a/dotnet/server_example_access_control/Program.cs +++ b/dotnet/server_example_access_control/Program.cs @@ -247,20 +247,40 @@ namespace server_access_control void LoadActiveSgValues(int actSG) { + 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); } + void LoadEditSgValues(int actSG) + { + DataObject strVal = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.StrVal"); + DataAttribute setMagF = strVal.GetChildWithFc("setMag.f", FunctionalConstraint.SE); + iedServer.UpdateFloatAttributeValue(setMagF, ptoc1Settings[actSG - 1].strVal); + + DataObject opDlTmms = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.OpDlTmms"); + DataAttribute setVal = opDlTmms.GetChildWithFc("setVal", FunctionalConstraint.SE); + iedServer.UpdateInt32AttributeValue(setVal, ptoc1Settings[actSG - 1].opDlTmms); + + DataObject rsDlTmms = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RsDlTmms"); + DataAttribute rsDlTmms_setVal = rsDlTmms.GetChildWithFc("setVal", FunctionalConstraint.SE); + iedServer.UpdateInt32AttributeValue(rsDlTmms_setVal, ptoc1Settings[actSG - 1].rsDlTmms); + + DataObject rstTms = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RstTms"); + DataAttribute rstTms_setVal = rstTms.GetChildWithFc("setVal", FunctionalConstraint.SE); + iedServer.UpdateInt32AttributeValue(rstTms_setVal, ptoc1Settings[actSG - 1].rstTms); + } + bool activeSGChangedHandler(object parameter, SettingGroupControlBlock sgcb, uint newActSg, ClientConnection connection) { Console.WriteLine("Switch to setting group "+ newActSg +"\n"); - LoadActiveSgValues(Convert.ToInt32(newActSg)); + return true; } @@ -268,6 +288,8 @@ namespace server_access_control { Console.WriteLine("Set edit setting group to " + newEditSg + "\n"); + LoadEditSgValues(Convert.ToInt32(newEditSg)); + return true; }