From 132264aead5ca81ada2f102746362b4e9b8d6e10 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Jun 2025 13:09:54 +0200 Subject: [PATCH 1/4] changed find DAI to a top down approach instead of bottom up --- .../SCLParser/src/DynamicModelGenerator.cs | 282 +++++------------- 1 file changed, 73 insertions(+), 209 deletions(-) diff --git a/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs b/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs index b0a26849..a4d6f78a 100644 --- a/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs +++ b/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs @@ -9,6 +9,7 @@ using IEC61850.SCL.DataModel; using System; using System.IO; +using System.Runtime.Serialization; namespace IEC61850.SCL { @@ -434,6 +435,33 @@ namespace IEC61850.SCL return null; } + SclDAI getNestedDAI(SclDOI initialDO, string name) + { + string[] parts = name.Split('.'); + + object obj = null; + Object foundObject = initialDO; + SclDAI sclDAI = null; + for( int i = 1; i < parts.Length; i++) + { + if (i == 1) + foundObject = initialDO.SclSDIs.Find(x => x.Name == parts[1]); + else if (i == parts.Length - 1) + { + SclSDI sclSDI = foundObject as SclSDI; + sclDAI = sclSDI?.SclDAIs.Find(x => x.Name == parts[i]); + + } + else + { + if (foundObject is SclSDI sclSDI) + foundObject = sclSDI.SclSDIs.Find(x => x.Name == parts[i]); + } + + } + return sclDAI; + } + DataObject findDOParent(DataAttribute dataAttribute) { DataObject parentObject = null; @@ -444,6 +472,10 @@ namespace IEC61850.SCL } parentObject = dataAttribute.Parent as DataObject; + while((parentObject.Parent is LogicalNode) == false) + { + parentObject = parentObject.Parent as DataObject; + } return parentObject; @@ -466,249 +498,81 @@ namespace IEC61850.SCL } - public SclDataAttributeDefinition GetDA(string name, SclDOType doType) - { - foreach (SclDataAttributeDefinition sclDa in doType.DataAttributes) - { - if (sclDa.Name != null && sclDa.Name.Equals(name)) - return sclDa; - } - - return null; - } - - SclDAI getDAIInternal(SclSDI sclSDI, DataAttribute dataAttribute) - { - SclDAI returnValue = null; - foreach (SclDAI sclDAI1 in sclSDI.SclDAIs) - { - if (sclDAI1.Name == dataAttribute.Name) - { - if (dataAttribute.ObjRef.EndsWith("." + sclSDI.Name + "." + sclDAI1.Name)) - { - returnValue = sclDAI1; - break; + //string recreateObjectReference(DataObject dataObject, SclSDI sclSDI, LogicalNode logicalNode) + //{ + // string result = ""; - } - } - } - - return returnValue; - } + // object parent = sclSDI.Parent; + // while (!(parent is SclDOI)) + // { + // SclSDI sclSDI1 = parent as SclSDI; + // parent = sclSDI1.Parent; - string getSDIValue(DataAttribute dataAttribute, object DIObject) - { - string value = null; + // result = result.Insert(0, "." + sclSDI1.Name); + // } + // SclDOI doName = (SclDOI)parent; + // result = result.Insert(0, doName.Name); - SclSDI sclSDI1 = DIObject as SclSDI; - if (sclSDI1 == null) - return value; + // LogicalDevice logicalDevice = logicalNode.Parent as LogicalDevice; + // result = result.Insert(0, logicalDevice.Name + "/" + logicalNode.Name + "."); - SclDAI sclDAI = getDAIInternal(sclSDI1, dataAttribute); - if (sclDAI != null) - { - value = sclDAI.Val; - } + // return result; + + //} - else - { - foreach (SclSDI sclSDI in sclSDI1.SclSDIs) - { - string fValue = getSDIValue(dataAttribute, sclSDI); - if (fValue != null) - { - value = fValue; - break; - } - } - } - - - return value; - - } - - string getDAIValue(DataAttribute dataAttribute, SclDOI sclDOI) + string getStippedObjRef(string objRef) { - if (sclDOI == null) - return null; + string result = ""; - string value = null; - SclDAI sclDAI = sclDOI.SclDAIs.Find(x => x.Name == dataAttribute.Name); - if (sclDAI != null) - { - value = sclDAI.Val; - } - else - { - foreach (SclSDI sclSDI in sclDOI.SclSDIs) - { - string fValue = getSDIValue(dataAttribute, sclSDI); - if (fValue != null) - { - value = fValue; - break; - } - } - - } + int index = objRef.IndexOf('.'); - return value; - - } - - string getObjRef(string initialString, SclSDI sclSDI) - { - object parent = sclSDI.Parent; - while (!(parent is SclDOI)) + if (index >= 0 && index < objRef.Length - 1) { - SclSDI sclSDI1 = parent as SclSDI; - parent = sclSDI1.Parent; + result = objRef.Substring(index + 1); } - SclDOI doName = (SclDOI)parent; - initialString += "." + doName.Name; - - return initialString; + return result; + } - SclDOI getDOIfromSDAI(SclSDI sclSDI) - { - object parent = sclSDI.Parent; - while (!(parent is SclDOI)) - { - SclSDI sclSDI1 = parent as SclSDI; - parent = sclSDI1.Parent; - } - SclDOI doName = (SclDOI)parent; - - - return doName; - } - SclSDI getSDIIInternal(SclSDI sclSDI, DataObject dataObject, LogicalNode logicalNode) - { - SclSDI returnValue = null; - foreach (SclSDI sclSDI1 in sclSDI.SclSDIs) - { - if (sclSDI1.Name == dataObject.Name) - { - string hh = ((LogicalDevice)logicalNode.Parent).Name + "/" + logicalNode.Name; - - string objRefString = getObjRef(hh, sclSDI); - if (dataObject.ObjRef.StartsWith(objRefString)) - { - - returnValue = sclSDI1; - break; - - } - } - } - - return returnValue; - } - - SclSDI getSDI(LogicalNode logicalNode, DataObject dataObject, object DIObject) - { - SclSDI returnValue = null; - SclSDI sclSDI1 = DIObject as SclSDI; - if (sclSDI1 == null) - return null; - - - SclSDI sclSDI_internal = getSDIIInternal(sclSDI1, dataObject, logicalNode); - - - if (sclSDI_internal != null) - { - - return sclSDI_internal; - } - - else - { - foreach (SclSDI sclSDI in sclSDI1.SclSDIs) - { - SclSDI sclSDI2 = getSDI(logicalNode, dataObject, sclSDI); - if (sclSDI2 != null) - { - returnValue = sclSDI2; - break; - } - - } - } - - - return returnValue; - - } - - SclDOI getSDO(LogicalNode logicalNode, DataObject dataObject) - { - SclSDI returnSDI = null; - - - foreach (SclDOI sclDOI1 in logicalNode.SclElement.DOIs) - { - foreach (SclSDI sclSDI in sclDOI1.SclSDIs) - { - returnSDI = getSDI(logicalNode, dataObject, sclSDI); - if (returnSDI != null) - { - break; - } - } - - if (returnSDI != null) - { - break; - } - } - if (returnSDI == null) - return null; - else - return getDOIfromSDAI(returnSDI); - - } void printDataAttributes(StreamWriter output, DataAttribute dataAttribute, bool isTransient) { - if (dataAttribute.ObjRef.Contains("serNum")) - { - Console.WriteLine("Debug"); - } - if (dataAttribute.AttributeType != AttributeType.CONSTRUCTED) { DataObject dataObject = findDOParent(dataAttribute); LogicalNode logicalNode = findLNParent(dataObject); + LogicalDevice logicalDevice = logicalNode.Parent as LogicalDevice; + + string value = ""; SclDOI sclDOI = logicalNode.SclElement.DOIs.Find(x => x.Name == dataObject.Name); - if (sclDOI == null) + if(sclDOI == null) { - sclDOI = getSDO(logicalNode, dataObject); - } - SclDAI sclDAI = getDAI(sclDOI, dataAttribute.Name); - - - string obValue = getDAIValue(dataAttribute, sclDOI); + output.WriteLine(";"); + return; - if (obValue == null) + } + SclDAI sclDAI = sclDOI.SclDAIs.Find(x => x.Name == dataAttribute.Name); + if (sclDAI != null && dataAttribute.ObjRef == logicalDevice.Name + "/" + logicalNode.Name + "." + sclDOI.Name + "." + sclDAI.Name) { - output.WriteLine(";"); + value = sclDAI.Val; + } - return; + else + { + string strippedObjRef = getStippedObjRef(dataAttribute.ObjRef); + sclDAI = getNestedDAI(sclDOI, strippedObjRef); + value = sclDAI?.Val; } - string value = obValue; if (value != null) { @@ -721,7 +585,7 @@ namespace IEC61850.SCL { if (sclEnumType.EnumValues.Count > 0) { - SclEnumVal sclEnumVal = sclEnumType.EnumValues[0]; + SclEnumVal sclEnumVal = sclEnumType.EnumValues.Find(x => x.SymbolicName == value); int value1 = sclEnumVal.Ord; output.Write("=" + sclEnumVal.Ord); From 0f3cf1a10ee4e14eb5b6994da5dad503f1a4432b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2025 13:04:22 +0200 Subject: [PATCH 2/4] fixed issue in displaying nested DAI values --- .../src/StaticModelGenerator.cs | 156 +++++++++++++++++- 1 file changed, 152 insertions(+), 4 deletions(-) diff --git a/tools/model_generator_dotnet/StaticModelGenerator/src/StaticModelGenerator.cs b/tools/model_generator_dotnet/StaticModelGenerator/src/StaticModelGenerator.cs index fc4395fd..5db75f09 100644 --- a/tools/model_generator_dotnet/StaticModelGenerator/src/StaticModelGenerator.cs +++ b/tools/model_generator_dotnet/StaticModelGenerator/src/StaticModelGenerator.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; +using System.Xml.Linq; using DataSet = IEC61850.SCL.DataModel.DataSet; namespace StaticModelGenerator @@ -318,6 +319,46 @@ namespace StaticModelGenerator return iecString.Replace('.', '$'); } + + DataObject findDOParent(DataAttribute dataAttribute) + { + DataObject parentObject = null; + + while (!(dataAttribute.Parent is DataObject)) + { + dataAttribute = dataAttribute.Parent as DataAttribute; + } + parentObject = dataAttribute.Parent as DataObject; + + while ((parentObject.Parent is LogicalNode) == false) + { + parentObject = parentObject.Parent as DataObject; + } + + return parentObject; + + + } + + LogicalNode findLNParent(DataObject dataObject) + { + LogicalNode parentObject = null; + + while (!(dataObject.Parent is LogicalNode)) + { + dataObject = dataObject.Parent as DataObject; + } + parentObject = dataObject.Parent as LogicalNode; + + + return parentObject; + + + } + + + + private void createDataObjectCStructure(List c_DO_DA_Structures, string dataAttributeSibling, string lnRef, DataObject dataObject, object parent, bool isTransiente, object sclDOI, int arrayIdx) { C_DataObjectStructure c_DataObjectStructure = new C_DataObjectStructure(); @@ -398,6 +439,10 @@ namespace StaticModelGenerator DataObjectOrAttribute dataObjectOrAttribute1 = dataObject.DataObjectsAndAttributes.First(); if (dataObjectOrAttribute1 is DataAttribute da) firstDataAttributeName = da.Name; + else + { + firstDataAttributeName = lnRef; + } c_ArrayDataObjectStructure.child = c_ArrayDataObjectStructure.objRef + "_" + dataObject.DataObjectsAndAttributes.First().Name; @@ -406,6 +451,8 @@ namespace StaticModelGenerator if (dataObjectOrAttribute is DataObject doObj) { SclSDI sclSDO = getSDI(sclDOI, dataObject.Name); + + firstDataAttributeName += "_" + dataObject.Name; createDataObjectCStructure(c_DO_DA_Structures, c_DataObjectStructure.objRef, firstDataAttributeName, doObj, dataObject, isDoTransient, sclSDO, -1); @@ -429,11 +476,17 @@ namespace StaticModelGenerator DataObjectOrAttribute dataObjectOrAttribute1 = dataObject.DataObjectsAndAttributes.First(); if (dataObjectOrAttribute1 is DataAttribute da) firstDataAttributeName = da.Name; + else + { + firstDataAttributeName = lnRef; + } foreach (DataObjectOrAttribute dataObjectOrAttribute in dataObject.DataObjectsAndAttributes) { if (dataObjectOrAttribute is DataObject doObj) { + firstDataAttributeName += "_" + dataObject.Name; + SclSDI sclSDO = getSDI(sclDOI, dataObject.Name); createDataObjectCStructure(c_DO_DA_Structures, c_DataObjectStructure.objRef, firstDataAttributeName, doObj, dataObject, isDoTransient, sclSDO, -1); @@ -604,11 +657,35 @@ namespace StaticModelGenerator } } - SclDAI sclDAI = getDAI(daiObj, dataAttribute.Name); + DataObject dataObject = findDOParent(dataAttribute); + LogicalNode logicalNode = findLNParent(dataObject); + LogicalDevice logicalDevice = logicalNode.Parent as LogicalDevice; + + string value = null; + + SclDOI sclDOI = logicalNode.SclElement.DOIs.Find(x => x.Name == dataObject.Name); + + SclDAI sclDAI1 = null; + + if (sclDOI != null) + { + + SclDAI sclDAI = sclDOI.SclDAIs.Find(x => x.Name == dataAttribute.Name); + if (sclDAI != null && dataAttribute.ObjRef == logicalDevice.Name + "/" + logicalNode.Name + "." + sclDOI.Name + "." + sclDAI.Name) + { + sclDAI1 = sclDAI; + } - if (sclDAI != null) - if (sclDAI.Val != null) - printValue(c_DataAttributeStructure, sclDAI.Val); + else + { + sclDAI1 = getNestedDAI(sclDOI, dataAttribute.ObjRef); + } + + } + + if (sclDAI1 != null) + if (sclDAI1.Val != null) + printValue(c_DataAttributeStructure, sclDAI1.Val); } SclDAI getDAI(object parent, string name) @@ -637,6 +714,67 @@ namespace StaticModelGenerator return null; } + SclSDI getSDINested(object parent, string name) + { + if (parent == null) + return null; + + if (parent is SclDOI sclDOI) + return sclDOI.SclSDIs.Find(x => x.Name == name); + else if (parent is SclSDI sclSDI) + return sclSDI.SclSDIs.Find(x => x.Name == name); + else + return null; + } + + + + string getStippedObjRef(string objRef) + { + string result = ""; + + int index = objRef.IndexOf('.'); + + if (index >= 0 && index < objRef.Length - 1) + { + result = objRef.Substring(index + 1); + } + + return result; + + } + + + SclDAI getNestedDAI(SclDOI initialDO, string name) + { + string strippedObjRef = getStippedObjRef(name); + + + string[] parts = strippedObjRef.Split('.'); + + object obj = null; + Object foundObject = initialDO; + SclDAI sclDAI = null; + for (int i = 1; i < parts.Length; i++) + { + if (i == 1) + foundObject = initialDO.SclSDIs.Find(x => x.Name == parts[1]); + else if (i == parts.Length - 1) + { + SclSDI sclSDI = foundObject as SclSDI; + sclDAI = sclSDI?.SclDAIs.Find(x => x.Name == parts[i]); + + } + else + { + if (foundObject is SclSDI sclSDI) + foundObject = sclSDI.SclSDIs.Find(x => x.Name == parts[i]); + } + + } + return sclDAI; + } + private void printValue(C_DataAttributeStructure c_DataAttributeStructure, string value) { C_InitializeValues c_InitializeValue = new C_InitializeValues(); @@ -653,6 +791,9 @@ namespace StaticModelGenerator switch (c_DataAttributeStructure.DataAttribute.AttributeType) { + case AttributeType.INT8: + case AttributeType.INT16: + case AttributeType.INT32: case AttributeType.INT64: c_InitializeValue.c_text += "MmsValue_newIntegerFromInt32(" + value + ");"; break; @@ -688,6 +829,9 @@ namespace StaticModelGenerator } break; + case AttributeType.INT8U: + case AttributeType.INT16U: + case AttributeType.INT24U: case AttributeType.INT32U: c_InitializeValue.c_text += "MmsValue_newUnsignedFromUint32(" + value + ");"; break; @@ -737,7 +881,11 @@ namespace StaticModelGenerator c_InitializeValue.c_text += "MmsValue_newUtcTimeByMsTime(" + value + ");"; break; + case AttributeType.VISIBLE_STRING_32: + case AttributeType.VISIBLE_STRING_64: + case AttributeType.VISIBLE_STRING_129: case AttributeType.VISIBLE_STRING_255: + case AttributeType.VISIBLE_STRING_65: c_InitializeValue.c_text += "MmsValue_newVisibleString(\"" + value + "\");"; break; From 5dcf973a323df736e20dccf297316fc30fe4d4ab Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2025 15:21:45 +0200 Subject: [PATCH 3/4] changed value from an empty string to null --- .../SCLParser/src/DynamicModelGenerator.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs b/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs index a4d6f78a..89dddb1b 100644 --- a/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs +++ b/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs @@ -546,11 +546,16 @@ namespace IEC61850.SCL if (dataAttribute.AttributeType != AttributeType.CONSTRUCTED) { + if (dataAttribute.ObjRef.Contains("stVal")) + { + Console.WriteLine("debug"); + } + DataObject dataObject = findDOParent(dataAttribute); LogicalNode logicalNode = findLNParent(dataObject); LogicalDevice logicalDevice = logicalNode.Parent as LogicalDevice; - string value = ""; + string value = null; SclDOI sclDOI = logicalNode.SclElement.DOIs.Find(x => x.Name == dataObject.Name); From c002f9e2ca610f050c7df4e23d2b4ef0a7048578 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Jun 2025 15:24:12 +0200 Subject: [PATCH 4/4] removed comment --- .../SCLParser/src/DynamicModelGenerator.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs b/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs index 89dddb1b..6c96460a 100644 --- a/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs +++ b/tools/model_generator_dotnet/SCLParser/src/DynamicModelGenerator.cs @@ -546,11 +546,6 @@ namespace IEC61850.SCL if (dataAttribute.AttributeType != AttributeType.CONSTRUCTED) { - if (dataAttribute.ObjRef.Contains("stVal")) - { - Console.WriteLine("debug"); - } - DataObject dataObject = findDOParent(dataAttribute); LogicalNode logicalNode = findLNParent(dataObject); LogicalDevice logicalDevice = logicalNode.Parent as LogicalDevice;