/* * Copyright 2013-2025 Michael Zillgith, MZ Automation GmbH * * This file is part of MZ Automation IEC 61850 SDK * * All rights reserved. */ using IEC61850.SCL.DataModel; using System; using System.IO; using System.Runtime.InteropServices.ComTypes; using System.Xml.Linq; namespace IEC61850.SCL { public class DynamicModelGenerator { private SclConnectedAP connectedAP = null; private SclIED ied = null; private bool hasOwner = false; private IEDDataModel iED = null; private SclDocument sclDocument; public DynamicModelGenerator(SclDocument sclDocument, StreamWriter output, IEDDataModel iED, SclAccessPoint accessPoint) { this.sclDocument = sclDocument; this.iED = iED; connectedAP = sclDocument.GetConnectedAP(accessPoint.Name, iED.Name); output.WriteLine("MODEL(" + iED.Name + "){"); foreach (LogicalDevice ld in iED.LogicalDevices) { output.Write("LD(" + ld.Inst + "){\n"); ExportLogicalNodes(output, ld); output.WriteLine("}"); } output.WriteLine("}"); } private void ExportLogicalNodes(StreamWriter output, LogicalDevice logicalDevice) { foreach (LogicalNode logicalNode in logicalDevice.LogicalNodes) { output.Write("LN(" + logicalNode.Name + "){\n"); ExportLogicalNode(output, logicalNode, logicalDevice); output.WriteLine("}"); } } private void ExportLogicalNode(StreamWriter output, LogicalNode logicalNode, LogicalDevice logicalDevice) { if (logicalNode.SettingControl != null) output.Write("SG(" + logicalNode.SettingControl.ActSG + " " + logicalNode.SettingControl.NumOfSGs + ")\n"); foreach (DataObject dataObject in logicalNode.DataObjects) { output.Write("DO(" + dataObject.Name + " " + dataObject.Count + "){\n"); ExportDataObject(output, dataObject, false); output.WriteLine("}"); } foreach (DataSet dataSet in logicalNode.DataSets) ExportDataSet(output, dataSet, logicalNode); foreach (ReportControl rcb in logicalNode.ReportControlBlocks) { if (rcb.SclReportControl.Indexed) { int maxInstances = 1; if (rcb.SclReportControl.RptEna != null) maxInstances = rcb.SclReportControl.RptEna.Max; for (int i = 0; i < maxInstances; i++) { string index = (i + 1).ToString("00"); PrintRCBInstance(output, rcb, index); } } else PrintRCBInstance(output, rcb, ""); } foreach (LogControl lcb in logicalNode.LogControls) PrintLCB(output, lcb, logicalNode, logicalDevice); foreach (Log log in logicalNode.Logs) output.WriteLine("LOG(" + log.Name + ");"); foreach (GSEControl gcb in logicalNode.GSEControls) { PrintGSEControl(output, gcb); } foreach (SMVControl smv in logicalNode.SMVControls) { PrintSMVControl(output, smv); } } private void PrintGSEControl(StreamWriter output, GSEControl gcb) { SclGSE gse = null; SclAddress gseAddress = null; if (connectedAP != null) { gse = connectedAP.GSEs.Find(x => x.CbName == gcb.Name); if (gse != null) gseAddress = gse.SclAddress; } else Console.WriteLine("WARNING: IED \"" + ied.Name + "\" has no connected access point!"); output.Write("GC("); output.Write(gcb.Name + " "); if (gcb.SclGSEControl.AppID != null) output.Write(gcb.SclGSEControl.AppID + " "); else output.Write("null "); if (gcb.SclGSEControl.DatSet != null) output.Write(gcb.SclGSEControl.DatSet + " "); else output.Write("null "); if (gcb.SclGSEControl.ConfRev >= 0) output.Write(gcb.SclGSEControl.ConfRev + " "); else output.Write("0 "); if (gcb.SclGSEControl.FixedOffs) output.Write('1'); else output.Write('0'); output.Write(' '); if (gse != null) { if (gse.Mintime != null) output.Write(gse.Mintime); else output.Write("0"); output.Write(' '); if (gse.Maxtime != null) output.Write(gse.Maxtime); else output.Write("0"); } else { output.Write("0 0"); } if (gseAddress == null) { output.WriteLine(");"); } else { output.WriteLine("){"); output.Write("PA("); output.Write(gseAddress.VlanPriority + " "); output.Write(gseAddress.VlanId + " "); output.Write(gseAddress.AppId + " "); for (int i = 0; i < 6; i++) { string hexValue = gseAddress.MacAddress[i].ToString("X2"); output.Write(hexValue); } output.WriteLine(");"); output.WriteLine("}"); } } private void PrintSMVControl(StreamWriter output, SMVControl smv) { SclSMV sclsmv = null; SclAddress smvAddress = null; if (connectedAP != null) { sclsmv = connectedAP.SMVs.Find(x => x.CbName == smv.Name); if (sclsmv != null) smvAddress = sclsmv.SclAddress; } output.Write("SMVC("); output.Write(smv.Name + " "); if (smv.SclSMVControl.SmvID != null) output.Write(smv.SclSMVControl.SmvID + " "); else output.Write("null "); if (smv.SclSMVControl.DataSet != null) output.Write(smv.SclSMVControl.DataSet + " "); else output.Write("null "); if (smv.SclSMVControl.ConfRev >= 0) output.Write(smv.SclSMVControl.ConfRev + " "); else output.Write("0 "); if (smv.SclSMVControl.SmpMod != null) output.Write(smv.SclSMVControl.SmpMod + " "); else output.Write("0 "); if(smv.SclSMVControl.SmpRate != -1) output.Write(smv.SclSMVControl.SmpRate + " "); else output.Write("0 "); //output.Write(smv.SclSMVControl.SmpRate + " "); if (smv.SclSMVControl.SclSmvOpts != null) output.Write(smv.SclSMVControl.SclSmvOpts.GetIntValue()); else output.Write("0"); output.Write(' '); if (smv.SclSMVControl.Multicast) output.Write('1'); else output.Write("0"); output.Write(' '); if (smvAddress == null) { output.WriteLine(");"); } else { output.WriteLine("){"); output.Write("PA("); output.Write(smvAddress.VlanPriority + " "); output.Write(smvAddress.VlanId + " "); output.Write(smvAddress.AppId + " "); for (int i = 0; i < 6; i++) { string hexValue = smvAddress.MacAddress[i].ToString("X2"); output.Write(hexValue); } output.WriteLine(");"); output.WriteLine("}"); } } private void PrintLCB(StreamWriter output, LogControl lcb, LogicalNode ln, LogicalDevice logicalDevice) { output.Write("LC("); output.Write(lcb.Name + " "); if (lcb.SclLogControl.DatSet != null && lcb.SclLogControl.DatSet != "") output.Write(lcb.SclLogControl.DatSet + " "); else output.Write("- "); if (lcb.SclLogControl.LogName != null && lcb.SclLogControl.LogName != "") { String logRef = logicalDevice.Inst + "/" + ln.Name + "$" + lcb.SclLogControl.LogName; output.Write(logRef + " "); } else output.Write("- "); if (lcb.SclLogControl.TrgOps != null) { output.Write(lcb.SclLogControl.TrgOps.GetIntValue() + " "); } if(lcb.SclLogControl.IntgPd is null) output.Write("0 "); else output.Write(lcb.SclLogControl.IntgPd + " "); if (lcb.SclLogControl.LogEna) output.Write("1 "); else output.Write("0 "); if (lcb.SclLogControl.ReasonCode) output.WriteLine("1);"); else output.WriteLine("0);"); } private void PrintRCBInstance(StreamWriter output, ReportControl rcb, string index) { output.Write("RC("); output.Write(rcb.Name + index + " "); if (rcb.SclReportControl.RptID != null) output.Write(rcb.SclReportControl.RptID + " "); else output.Write("- "); if (rcb.SclReportControl.Buffered) output.Write("1 "); else output.Write("0 "); if (rcb.SclReportControl.DatSet != null) output.Write(rcb.SclReportControl.DatSet + " "); else output.Write("- "); if (rcb.SclReportControl.IntConfRev >= 0) output.Write(rcb.SclReportControl.IntConfRev + " "); else output.Write("0 "); int triggerOptions = 0; if (rcb.SclReportControl.TrgOps != null) { triggerOptions = rcb.SclReportControl.TrgOps.GetIntValue(); } if (hasOwner) triggerOptions += 64; output.Write(triggerOptions + " "); int OptFields = 0; if (rcb.SclReportControl.OptFields != null) { OptFields = rcb.SclReportControl.OptFields.GetIntValue(); } output.Write(OptFields + " "); if (rcb.SclReportControl.BufTime != null) output.Write(rcb.SclReportControl.BufTime + " "); else output.Write("0 "); if (rcb.SclReportControl.IntgPd != null) output.Write(rcb.SclReportControl.IntgPd); else output.Write("0"); output.WriteLine(");"); } private void exportDataObjectChild(StreamWriter output, DataObject dataObject, bool isTransient) { foreach (DataObjectOrAttribute child in dataObject.DataObjectsAndAttributes) { if (child is DataObject) { DataObject subDataObject = child as DataObject; output.Write("DO(" + subDataObject.Name + " " + subDataObject.Count + "){\n"); ExportDataObject(output, subDataObject, isTransient); output.WriteLine("}"); } else { DataAttribute dataAttribute = child as DataAttribute; ExportDataAttribute(output, dataAttribute, isTransient); } } } private void ExportDataObject(StreamWriter output, DataObject dataObject, bool isTransient) { if (dataObject.IsTransiente) isTransient = true; if (dataObject.Count > 0) { /* data object is an array */ for (int i = 0; i < dataObject.Count; i++) { output.WriteLine("[" + i + "]{\n"); exportDataObjectChild(output, dataObject, isTransient); output.Write("}\n"); } } else { exportDataObjectChild(output, dataObject, isTransient); } } //private void printDataAttributeValue(StreamWriter output, DataAttribute dataAttribute, bool isTransient) //{ // if (dataAttribute.AttributeType != AttributeType.CONSTRUCTED) // { // SclVal value = dataAttribute.Definition.GetVal(); // /* if no value is given use default value for type if present */ // if (value == null) // { // value = dataAttribute.Definition.GetVal(); // //if (value != null) // // if (value.Value == null) // // value.updateEnumOrdValue(ied.getTypeDeclarations()); // } // if (value != null) // { // switch (dataAttribute.AttributeType) // { // case AttributeType.ENUMERATED: // case AttributeType.INT8: // case AttributeType.INT16: // case AttributeType.INT32: // case AttributeType.INT64: // output.Write("=" + value.Value()); // break; // case AttributeType.INT8U: // case AttributeType.INT16U: // case AttributeType.INT24U: // case AttributeType.INT32U: // output.Write("=" + value.getLongValue()); // break; // case AttributeType.BOOLEAN: // { // Boolean boolVal = (Boolean)value.getValue(); // if (boolVal.booleanValue()) // output.print("=1"); // } // break; // case AttributeType.UNICODE_STRING_255: // output.print("=\"" + value.getValue() + "\""); // break; // case AttributeType.CURRENCY: // 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: // output.Write("=\"" + value.getValue() + "\""); // break; // case AttributeType.FLOAT32: // case AttributeType.FLOAT64: // output.Write("=" + value.getValue()); // break; // case AttributeType.TIMESTAMP: // case AttributeType.ENTRY_TIME: // output.Write("=" + value.getLongValue()); // break; // default: // System.out.println("Unknown default value for " + dataAttribute.getName() + " type: " + dataAttribute.getType()); // break; // } // } // output.Write(";"); // } // else // { // output.Write("{"); // foreach (DataAttribute subDataAttribute in dataAttribute.subDataAttributes) // { // ExportDataAttribute(output, subDataAttribute, isTransient); // } // output.Write("}"); // } //} SclDAI getDAI(object parent, string name) { if (parent == null) return null; if (parent is SclDOI sclDOI) return sclDOI.SclDAIs.Find(x => x.Name == name); else if (parent is SclSDI sclSDI) return sclSDI.SclDAIs.Find(x => x.Name == name); else return null; } DataObject findDOParent(DataAttribute dataAttribute) { DataObject parentObject = null; //DataObjectOrAttribute obj = null; while(!(dataAttribute.Parent is DataObject)) { dataAttribute = dataAttribute.Parent as DataAttribute; } parentObject = dataAttribute.Parent as DataObject; return parentObject; } LogicalNode findLNParent(DataObject dataObject) { LogicalNode parentObject = null; //DataObjectOrAttribute obj = null; while (!(dataObject.Parent is LogicalNode)) { dataObject = dataObject.Parent as DataObject; } parentObject = dataObject.Parent as LogicalNode; return parentObject; } 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; } //private void SetPredefindedValuesForDAI(LogicalNode ln, DataAttribute dataAttribute, DataObject dataObject) //{ // if (dai.Name != null) // { //} //private void SetPredefinedValuesForSDI(LogicalNode ln, string path, SclSDI sclSdi, SclDOType doType, SclDAType daType, SclDataTypeTemplates types, DataAttribute dataAttribute) //{ // if (sclSdi.Name != null) // { // string extendedPath = path + "." + sclSdi.Name; // foreach (SclDAI dai in sclSdi.SclDAIs) // { // if (doType != null) // { // SclDataAttributeDefinition sclDa = GetDA(dai.Name, doType); // if (sclDa != null) // { // DataAttributeType bType = (DataAttributeType)sclDa.AttributeType; // SetPredefindedValuesForDAI(ln, extendedPath, dai, bType, sclDa.Type, types); // } // else // { // logMessage(IedModelFactoryLogLevel.ERROR, "SCL: DA for name " + dai.Name + " not found"); // } // } // else if (daType != null) // { // SclDataAttributeDefinition sclBda = daType.GetBDA(dai.Name); // if (sclBda != null) // { // DataAttributeType bType = (DataAttributeType)sclBda.AttributeType; // SetPredefindedValuesForDAI(ln, extendedPath, dai, bType, sclBda.Type, types); // } // } // } // foreach (SclSDI sdi in sclSdi.SclSDIs) // { // if (doType != null) // { // SclDataAttributeDefinition da = doType.GetDA(sdi.Name, dataAttribute); // if (da != null) // { // SclDAType subDaType = types.GetDAType(da.Type); // if (subDaType != null) // { // SetPredefinedValuesForSDI(ln, extendedPath, sdi, null, subDaType, types); // } // } // else // { // SclDataObjectDefinition sdo = doType.GetSDO(sdi.Name); // if (sdo != null) // { // SclDOType subDoType = types.GetDOType(sdo.Type); // if (subDoType != null) // { // SetPredefinedValuesForSDI(ln, extendedPath, sdi, subDoType, null, types); // } // } // } // } // else if (daType != null) // { // SclDataAttributeDefinition bda = daType.GetBDA(sdi.Name); // if (bda != null) // { // SclDAType subDaType = types.GetDAType(bda.Type); // if (subDaType != null) // { // SetPredefinedValuesForSDI(ln, extendedPath, sdi, null, subDaType, types); // } // } // } // } // } //} //object findValue(DataAttribute dataAttribute) //{ // object value = null; // if(dataAttribute.Parent is DataAttribute dataAttribute1) // { // SclDAI sclDAI = getDAI(dataAttribute1.Parent, dataAttribute.Name); // SclSDO sclSDOI = null; // sclSDOI. // } // return value; //} 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; } } } return returnValue; } string getSDIValue(DataAttribute dataAttribute, object DIObject) { string value = null; SclSDI sclSDI1 = DIObject as SclSDI; if (sclSDI1 == null) return value; SclDAI sclDAI = getDAIInternal(sclSDI1, dataAttribute); if (sclDAI != null) { value = sclDAI.Val; } 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) { if (sclDOI == null) return null; 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; } } } return value; } string getObjRef(string initialString, SclSDI sclSDI) { object parent = sclSDI.Parent; while(!(parent is SclDOI)) { SclSDI sclSDI1 = parent as SclSDI; parent = sclSDI1.Parent; } SclDOI doName = (SclDOI)parent; initialString += "." + doName.Name; return initialString; } 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) { //if (value != null) //{ DataObject dataObject = findDOParent(dataAttribute); //DataObject dataObject = dataAttribute.Parent as DataObject; //LogicalNode logicalNode = dataObject.Parent as LogicalNode; LogicalNode logicalNode = findLNParent(dataObject); SclDOI sclDOI = logicalNode.SclElement.DOIs.Find(x => x.Name == dataObject.Name); if(sclDOI == null) { sclDOI = getSDO(logicalNode, dataObject); } SclDAI sclDAI = getDAI(sclDOI, dataAttribute.Name); string obValue = getDAIValue(dataAttribute, sclDOI); if (obValue == null) { output.WriteLine(";"); return; } //string value = sclDAI.Val; string value = obValue; if (value != null) { switch (dataAttribute.AttributeType) { case AttributeType.ENUMERATED: SclEnumType sclEnumType = sclDocument.DataTypeTemplates.GetEnumType(dataAttribute.Definition.Type); if (sclEnumType != null) { if (sclEnumType.EnumValues.Count > 0) { SclEnumVal sclEnumVal = sclEnumType.EnumValues[0]; int value1 = sclEnumVal.Ord; output.Write("=" + sclEnumVal.Ord); } } break; case AttributeType.INT8: case AttributeType.INT16: case AttributeType.INT32: case AttributeType.INT64: case AttributeType.INT8U: case AttributeType.INT16U: case AttributeType.INT24U: case AttributeType.INT32U: output.Write("=" + value); break; case AttributeType.BOOLEAN: if (value == "true") output.Write("=1"); else output.Write("=0"); break; case AttributeType.UNICODE_STRING_255: output.Write("=\"" + value + "\""); break; case AttributeType.CURRENCY: 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: output.Write("=\"" + value + "\""); break; case AttributeType.OCTET_STRING_64: output.Write("=\"" + value + "\""); break; case AttributeType.FLOAT32: case AttributeType.FLOAT64: output.Write("=" + value); break; default: Console.WriteLine("Unknown default value for " + dataAttribute.Name + " type: " + dataAttribute.AttributeType); break; } //} } output.WriteLine(";"); } else { output.WriteLine("{"); foreach (DataAttribute subDataAttribute in dataAttribute.SubDataAttributes) { ExportDataAttribute(output, subDataAttribute, isTransient); } output.WriteLine("}"); } } private void ExportDataAttribute(StreamWriter output, DataAttribute dataAttribute, bool isTransient) { output.Write("DA(" + dataAttribute.Name + " "); output.Write(dataAttribute.Count + " "); output.Write((int)dataAttribute.AttributeType + " "); output.Write((int)dataAttribute.Fc + " "); if (dataAttribute.Definition.TriggerOptions != null) { int trgOpsVal = dataAttribute.Definition.TriggerOptions.GetIntValue(); if (isTransient) trgOpsVal += 128; output.Write(trgOpsVal + " "); } if (dataAttribute.Definition.SAddr != null) output.Write(dataAttribute.Definition.SAddr); else output.Write("0"); output.Write(")"); if (dataAttribute.Count > 0) { output.WriteLine("{"); for (int i = 0; i < dataAttribute.Count; i++) { output.Write("[" + i + "]"); printDataAttributes(output, dataAttribute, isTransient); } output.WriteLine("}"); } else { printDataAttributes(output, dataAttribute, isTransient); } //if (value != null) //{ // switch (dataAttribute.AttributeType) // { // case AttributeType.ENUMERATED: // string EnumType = dataAttribute.Definition.Type; // SclEnumType sclEnumType; // if (EnumType != null) // { // sclEnumType = sclDocument.DataTypeTemplates.GetEnumType(EnumType); // if (sclEnumType != null) // { // SclEnumVal sclEnumVal = sclEnumType.EnumValues.Find(x => x.SymbolicName == value.Value); // output.Write("=" + sclEnumVal.Ord); // } // } // break; // case AttributeType.INT8: // case AttributeType.INT16: // case AttributeType.INT32: // case AttributeType.INT64: // output.Write("=" + value.Value); // break; // case AttributeType.INT8U: // case AttributeType.INT16U: // case AttributeType.INT24U: // case AttributeType.INT32U: // output.Write("=" + value.Value); // break; // case AttributeType.BOOLEAN: // if (value.Value == "true") // output.Write("=1"); // else // output.Write("=0"); // break; // case AttributeType.UNICODE_STRING_255: // output.Write("=\"" + value.Value + "\""); // break; // case AttributeType.CURRENCY: // 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: // output.Write("=\"" + value.Value + "\""); // break; // case AttributeType.OCTET_STRING_64: // output.Write("=\"" + value.Value + "\""); // break; // case AttributeType.FLOAT32: // case AttributeType.FLOAT64: // output.Write("=" + value.Value); // break; // default: // Console.WriteLine("Unknown default value for " + dataAttribute.Name + " type: " + dataAttribute.AttributeType); // break; // } //} //output.WriteLine(";"); //} } private static String toMmsString(String iecString) { return iecString.Replace('.', '$'); } private void ExportDataSet(StreamWriter output, DataSet dataSet, LogicalNode logicalNode) { output.Write("DS(" + dataSet.Name + "){\n"); foreach (SclFCDA fcda in dataSet.SclDataSet.Fcdas) { String mmsVariableName = ""; if (fcda.Prefix != null) mmsVariableName += fcda.Prefix; mmsVariableName += fcda.LnClass; if (fcda.LnInst != null) mmsVariableName += fcda.LnInst; mmsVariableName += "$" + fcda.Fc; mmsVariableName += "$" + fcda.DoName; if (fcda.DaName != null) mmsVariableName += "$" + toMmsString(fcda.DaName); int arrayStart = mmsVariableName.IndexOf('('); String variableName = mmsVariableName; int arrayIndex = -1; string componentName = null; if (arrayStart != -1) { variableName = mmsVariableName.Substring(0, arrayStart); int arrayEnd = mmsVariableName.IndexOf(')'); string arrayIndexStr = mmsVariableName.Substring(arrayStart + 1, arrayEnd); arrayIndex = int.Parse(arrayIndexStr); //if (arrayIndex < 0) // throw new SclParserException("Array index out of range in data set entry definition"); string componentNamePart = mmsVariableName.Substring(arrayEnd + 1); if ((componentNamePart != null) && (componentNamePart.Length > 0)) { if (componentNamePart[0] == '$') { componentNamePart = componentNamePart.Substring(1); } if ((componentNamePart != null) && (componentNamePart.Length > 0)) componentName = componentNamePart; } } /* check for LD name */ String logicalDeviceName = null; if (fcda.LdInst != null) { if (fcda.LdInst != (logicalNode.Parent as LogicalDevice).Inst) { logicalDeviceName = fcda.LdInst; } } if (logicalDeviceName != null) variableName = logicalDeviceName + "/" + variableName; if (variableName != null && arrayIndex != -1 && componentName != null) { output.Write("DE(" + variableName + " " + arrayIndex + " " + componentName + ");\n"); } else if (variableName != null && arrayIndex != -1) { output.Write("DE(" + variableName + " " + arrayIndex + ");\n"); } else if (variableName != null) { output.Write("DE(" + variableName + ");\n"); } } output.WriteLine("}"); } } }