- .NET API: Added additional ModelNode methods. Added additional method IedServer.HandleWriteAccessForComplexAttribute. Fixed some problems with WriteAccessHandler.

pull/331/head
Michael Zillgith 5 years ago
parent 842bc271cd
commit d5d8b70dc2

@ -81,6 +81,9 @@ namespace IEC61850
this.self = self; this.self = self;
} }
/* cache managed ModelNode instances of the IedModel */
internal Dictionary<IntPtr, ModelNode> modelNodes = new Dictionary<IntPtr, ModelNode>();
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:IEC61850.Server.IedModel"/> class. /// Initializes a new instance of the <see cref="T:IEC61850.Server.IedModel"/> class.
/// </summary> /// </summary>
@ -132,26 +135,112 @@ namespace IEC61850
return ConfigFileParser.CreateModelFromConfigFile(filename); return ConfigFileParser.CreateModelFromConfigFile(filename);
} }
private ModelNode getModelNodeFromNodeRef(IntPtr nodeRef) /// <summary>
/// Get parent node. When not found create the parent node and add to modelNode list
/// </summary>
/// <returns>The parent node, or <see langword="null"/> when not found</returns>
/// <param name="nodeRef">the native reference of the model node</param>
private ModelNode GetParent(IntPtr nodeRef)
{
ModelNode parentNode = null;
IntPtr parentNodeRef = ModelNode.GetNativeParent(nodeRef);
if (parentNodeRef != IntPtr.Zero)
{
if (modelNodes.TryGetValue(parentNodeRef, out parentNode) == false)
{
int nodeType = ModelNode_getType(parentNodeRef);
if (nodeType == 0)
{
parentNode = new LogicalDevice(parentNodeRef, this);
}
else
{
ModelNode parentOfParent = GetParent(parentNodeRef);
if (parentOfParent != null)
{
switch (nodeType)
{
case 1:
parentNode = new LogicalNode(parentNodeRef, parentOfParent);
break;
case 2:
parentNode = new DataObject(parentNodeRef, parentOfParent);
break;
case 3:
parentNode = new DataAttribute(parentNodeRef, parentOfParent);
break;
default:
parentNode = new ModelNode(parentNodeRef, parentOfParent);
break;
}
}
}
if (parentNode != null)
{
modelNodes.Add(parentNodeRef, parentNode);
}
}
}
return parentNode;
}
private ModelNode GetModelNodeFromNodeRef(IntPtr nodeRef)
{
ModelNode modelNode = null;
modelNodes.TryGetValue(nodeRef, out modelNode);
if (modelNode == null)
{ {
int nodeType = ModelNode_getType(nodeRef); int nodeType = ModelNode_getType(nodeRef);
switch (nodeType) { if (nodeType == 0)
case 0: {
return new LogicalDevice (nodeRef); modelNode = new LogicalDevice(nodeRef, this);
}
else
{
ModelNode parent = GetParent(nodeRef);
if (parent != null)
{
switch (nodeType)
{
case 1: case 1:
return new LogicalNode (nodeRef); modelNode = new LogicalNode(nodeRef, parent);
break;
case 2: case 2:
return new DataObject (nodeRef); modelNode = new DataObject(nodeRef, parent);
break;
case 3: case 3:
return new DataAttribute (nodeRef); modelNode = new DataAttribute(nodeRef, parent);
break;
default: default:
return new ModelNode (nodeRef); modelNode = new ModelNode(nodeRef, parent);
break;
}
}
}
if (modelNode != null)
{
modelNodes.Add(nodeRef, modelNode);
}
} }
return modelNode;
} }
/// <summary> /// <summary>
@ -175,7 +264,7 @@ namespace IEC61850
if (nodeRef == IntPtr.Zero) if (nodeRef == IntPtr.Zero)
return null; return null;
return getModelNodeFromNodeRef (nodeRef); return GetModelNodeFromNodeRef (nodeRef);
} }
/// <summary> /// <summary>
@ -190,7 +279,7 @@ namespace IEC61850
if (nodeRef == IntPtr.Zero) if (nodeRef == IntPtr.Zero)
return null; return null;
return getModelNodeFromNodeRef (nodeRef); return GetModelNodeFromNodeRef (nodeRef);
} }
} }
@ -200,12 +289,19 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr LogicalDevice_create(string name, IntPtr parent); static extern IntPtr LogicalDevice_create(string name, IntPtr parent);
public LogicalDevice (IntPtr self) : base (self) private IedModel iedModel = null;
public IedModel IedModel { get => iedModel; }
public LogicalDevice (IntPtr self, IedModel iedModel) : base (self)
{ {
this.iedModel = iedModel;
} }
public LogicalDevice(string name, IedModel parent) public LogicalDevice(string name, IedModel parent)
{ {
this.iedModel = parent;
self = LogicalDevice_create(name, parent.self); self = LogicalDevice_create(name, parent.self);
} }
} }
@ -215,12 +311,15 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr LogicalNode_create(string name, IntPtr parent); static extern IntPtr LogicalNode_create(string name, IntPtr parent);
public LogicalNode (IntPtr self) : base(self) public LogicalNode (IntPtr self, ModelNode parent) : base(self)
{ {
this.parent = parent;
} }
public LogicalNode(string name, LogicalDevice parent) public LogicalNode(string name, LogicalDevice parent)
{ {
this.parent = parent;
base.self = LogicalNode_create(name, parent.self); base.self = LogicalNode_create(name, parent.self);
} }
} }
@ -411,7 +510,7 @@ namespace IEC61850
IntPtr self = CDC_SPS_create(name, parent.self, options); IntPtr self = CDC_SPS_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject (self); return new DataObject (self, parent);
else else
return null; return null;
} }
@ -421,7 +520,7 @@ namespace IEC61850
IntPtr self = CDC_DPS_create(name, parent.self, options); IntPtr self = CDC_DPS_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -431,7 +530,7 @@ namespace IEC61850
IntPtr self = CDC_VSS_create(name, parent.self, options); IntPtr self = CDC_VSS_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -441,7 +540,7 @@ namespace IEC61850
IntPtr self = CDC_SEC_create(name, parent.self, options); IntPtr self = CDC_SEC_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -451,7 +550,7 @@ namespace IEC61850
IntPtr self = CDC_CMV_create(name, parent.self, options); IntPtr self = CDC_CMV_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -461,7 +560,7 @@ namespace IEC61850
IntPtr self = CDC_SAV_create(name, parent.self, options, isIntegerNotFloat); IntPtr self = CDC_SAV_create(name, parent.self, options, isIntegerNotFloat);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -471,7 +570,7 @@ namespace IEC61850
IntPtr self = CDC_ACD_create(name, parent.self, options); IntPtr self = CDC_ACD_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -481,7 +580,7 @@ namespace IEC61850
IntPtr self = CDC_ACT_create(name, parent.self, options); IntPtr self = CDC_ACT_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -491,7 +590,7 @@ namespace IEC61850
IntPtr self = CDC_SPG_create(name, parent.self, options); IntPtr self = CDC_SPG_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -501,7 +600,7 @@ namespace IEC61850
IntPtr self = CDC_VSG_create(name, parent.self, options); IntPtr self = CDC_VSG_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -511,7 +610,7 @@ namespace IEC61850
IntPtr self = CDC_ENG_create(name, parent.self, options); IntPtr self = CDC_ENG_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -521,7 +620,7 @@ namespace IEC61850
IntPtr self = CDC_ING_create(name, parent.self, options); IntPtr self = CDC_ING_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -531,7 +630,7 @@ namespace IEC61850
IntPtr self = CDC_ASG_create(name, parent.self, options, isIntegerNotFloat); IntPtr self = CDC_ASG_create(name, parent.self, options, isIntegerNotFloat);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -541,7 +640,7 @@ namespace IEC61850
IntPtr self = CDC_WYE_create(name, parent.self, options); IntPtr self = CDC_WYE_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -551,7 +650,7 @@ namespace IEC61850
IntPtr self = CDC_DEL_create(name, parent.self, options); IntPtr self = CDC_DEL_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -561,7 +660,7 @@ namespace IEC61850
IntPtr self = CDC_HST_create(name, parent.self, options, maxPts); IntPtr self = CDC_HST_create(name, parent.self, options, maxPts);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -571,7 +670,7 @@ namespace IEC61850
IntPtr self = CDC_INS_create(name, parent.self, options); IntPtr self = CDC_INS_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject (self); return new DataObject (self, parent);
else else
return null; return null;
} }
@ -581,7 +680,7 @@ namespace IEC61850
IntPtr self = CDC_MV_create(name, parent.self, options, isIntegerNotFloat); IntPtr self = CDC_MV_create(name, parent.self, options, isIntegerNotFloat);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject (self); return new DataObject (self, parent);
else else
return null; return null;
} }
@ -591,7 +690,7 @@ namespace IEC61850
IntPtr self = CDC_INC_create(name, parent.self, options, controlOptions); IntPtr self = CDC_INC_create(name, parent.self, options, controlOptions);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject (self); return new DataObject (self, parent);
else else
return null; return null;
} }
@ -601,7 +700,7 @@ namespace IEC61850
IntPtr self = CDC_LPL_create(name, parent.self, options); IntPtr self = CDC_LPL_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject (self); return new DataObject (self, parent);
else else
return null; return null;
} }
@ -611,7 +710,7 @@ namespace IEC61850
IntPtr self = CDC_DPL_create(name, parent.self, options); IntPtr self = CDC_DPL_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject (self); return new DataObject (self, parent);
else else
return null; return null;
} }
@ -621,7 +720,7 @@ namespace IEC61850
IntPtr self = CDC_ENS_create(name, parent.self, options); IntPtr self = CDC_ENS_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -631,7 +730,7 @@ namespace IEC61850
IntPtr self = CDC_SPC_create(name, parent.self, options, controlOptions); IntPtr self = CDC_SPC_create(name, parent.self, options, controlOptions);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -641,7 +740,7 @@ namespace IEC61850
IntPtr self = CDC_DPC_create(name, parent.self, options, controlOptions); IntPtr self = CDC_DPC_create(name, parent.self, options, controlOptions);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -651,7 +750,7 @@ namespace IEC61850
IntPtr self = CDC_BSC_create(name, parent.self, options, controlOptions, hasTransientIndicator); IntPtr self = CDC_BSC_create(name, parent.self, options, controlOptions, hasTransientIndicator);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -661,7 +760,7 @@ namespace IEC61850
IntPtr self = CDC_APC_create(name, parent.self, options, controlOptions, isIntegerNotFloat); IntPtr self = CDC_APC_create(name, parent.self, options, controlOptions, isIntegerNotFloat);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -671,7 +770,7 @@ namespace IEC61850
IntPtr self = CDC_BCR_create(name, parent.self, options); IntPtr self = CDC_BCR_create(name, parent.self, options);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -681,7 +780,7 @@ namespace IEC61850
IntPtr self = CDC_ENC_create(name, parent.self, options, controlOptions); IntPtr self = CDC_ENC_create(name, parent.self, options, controlOptions);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -691,7 +790,7 @@ namespace IEC61850
IntPtr self = CDC_SPV_create(name, parent.self, options, controlOptions, wpOptions, hasChaManRs); IntPtr self = CDC_SPV_create(name, parent.self, options, controlOptions, wpOptions, hasChaManRs);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -701,7 +800,7 @@ namespace IEC61850
IntPtr self = CDC_STV_create(name, parent.self, options, controlOptions, wpOptions, hasOldStatus); IntPtr self = CDC_STV_create(name, parent.self, options, controlOptions, wpOptions, hasOldStatus);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -711,7 +810,7 @@ namespace IEC61850
IntPtr self = CDC_CMD_create(name, parent.self, options, controlOptions, wpOptions, hasOldStatus, hasCmTm, hasCmCt); IntPtr self = CDC_CMD_create(name, parent.self, options, controlOptions, wpOptions, hasOldStatus, hasCmTm, hasCmCt);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -721,7 +820,7 @@ namespace IEC61850
IntPtr self = CDC_ALM_create(name, parent.self, options, controlOptions, wpOptions, hasOldStatus); IntPtr self = CDC_ALM_create(name, parent.self, options, controlOptions, wpOptions, hasOldStatus);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -731,7 +830,7 @@ namespace IEC61850
IntPtr self = CDC_CTE_create(name, parent.self, options, controlOptions, wpOptions, hasHisRs); IntPtr self = CDC_CTE_create(name, parent.self, options, controlOptions, wpOptions, hasHisRs);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -741,7 +840,7 @@ namespace IEC61850
IntPtr self = CDC_TMS_create(name, parent.self, options, controlOptions, wpOptions, hasHisRs); IntPtr self = CDC_TMS_create(name, parent.self, options, controlOptions, wpOptions, hasHisRs);
if (self != IntPtr.Zero) if (self != IntPtr.Zero)
return new DataObject(self); return new DataObject(self, parent);
else else
return null; return null;
} }
@ -752,8 +851,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr DataObject_create(string name, IntPtr parent, int arrayElements); static extern IntPtr DataObject_create(string name, IntPtr parent, int arrayElements);
internal DataObject(IntPtr self) : base(self) internal DataObject(IntPtr self, ModelNode parent) : base(self)
{ {
this.parent = parent;
} }
public DataObject(string name, ModelNode parent) : this(name, parent, 0) public DataObject(string name, ModelNode parent) : this(name, parent, 0)
@ -762,6 +862,8 @@ namespace IEC61850
public DataObject(string name, ModelNode parent, int arrayElements) public DataObject(string name, ModelNode parent, int arrayElements)
{ {
this.parent = parent;
self = DataObject_create (name, parent.self, arrayElements); self = DataObject_create (name, parent.self, arrayElements);
} }
@ -774,13 +876,16 @@ namespace IEC61850
static extern IntPtr DataAttribute_create(string name, IntPtr parent, int type, int fc, static extern IntPtr DataAttribute_create(string name, IntPtr parent, int type, int fc,
byte triggerOptions, int arrayElements, UInt32 sAddr); byte triggerOptions, int arrayElements, UInt32 sAddr);
internal DataAttribute(IntPtr self) : base(self) internal DataAttribute(IntPtr self, ModelNode parent) : base(self)
{ {
this.parent = parent;
} }
public DataAttribute (string name, ModelNode parent, DataAttributeType type, FunctionalConstraint fc, TriggerOptions trgOps, public DataAttribute (string name, ModelNode parent, DataAttributeType type, FunctionalConstraint fc, TriggerOptions trgOps,
int arrayElements, UInt32 sAddr) int arrayElements, UInt32 sAddr)
{ {
this.parent = parent;
self = DataAttribute_create (name, parent.self, (int)type, (int)fc, (byte)trgOps, arrayElements, sAddr); self = DataAttribute_create (name, parent.self, (int)type, (int)fc, (byte)trgOps, arrayElements, sAddr);
} }
@ -800,17 +905,95 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ModelNode_getObjectReferenceEx(IntPtr self, IntPtr objectReference, [MarshalAs(UnmanagedType.I1)] bool withoutIedName); static extern IntPtr ModelNode_getObjectReferenceEx(IntPtr self, IntPtr objectReference, [MarshalAs(UnmanagedType.I1)] bool withoutIedName);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ModelNode_getParent(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ModelNode_getChildren(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ModelNode_getName(IntPtr self);
/****************
* LinkedList
***************/
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr LinkedList_getNext(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr LinkedList_getData(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void LinkedList_destroyStatic(IntPtr self);
public IntPtr self; public IntPtr self;
internal ModelNode parent = null;
static internal IntPtr GetNativeParent(IntPtr self)
{
return ModelNode_getParent(self);
}
internal ModelNode() internal ModelNode()
{ {
self = IntPtr.Zero;
}
internal ModelNode(IntPtr self, ModelNode parent)
{
this.self = self;
this.parent = parent;
} }
public ModelNode(IntPtr self) internal ModelNode(IntPtr self)
{ {
this.self = self; this.self = self;
} }
/// <summary>
/// Gets the IedModel for this ModelNode instance
/// </summary>
/// <returns>the IedModel instance of this ModelNode.</returns>
public IedModel GetIedModel()
{
if (this is LogicalDevice)
{
return (this as LogicalDevice).IedModel;
}
else
{
if (this.parent != null)
return parent.GetIedModel();
else
return null;
}
}
/// <summary>
/// Gets the name of the model node
/// </summary>
/// <returns>name of the model node</returns>
public string GetName()
{
return Marshal.PtrToStringAnsi(ModelNode_getName(self));
}
/// <summary>
/// Gets the parent node of this model node
/// </summary>
/// <returns>The parent node</returns>
public ModelNode GetParent()
{
return parent;
}
/// <summary>
/// Get the child node of this model node with the given name
/// </summary>
/// <returns>The child node or null when there is no child with the given name</returns>
/// <param name="name">name of the child node</param>
public ModelNode GetChild(string name) public ModelNode GetChild(string name)
{ {
IntPtr childPtr = ModelNode_getChild(self, name); IntPtr childPtr = ModelNode_getChild(self, name);
@ -818,25 +1001,127 @@ namespace IEC61850
if (childPtr == IntPtr.Zero) if (childPtr == IntPtr.Zero)
return null; return null;
ModelNode child = null;
IedModel iedModel = GetIedModel();
if (iedModel != null)
{
iedModel.modelNodes.TryGetValue(childPtr, out child);
}
if (child == null)
{
int nodeType = ModelNode_getType(childPtr); int nodeType = ModelNode_getType(childPtr);
switch (nodeType) { switch (nodeType)
{
case 0: case 0:
return new LogicalDevice (childPtr); child = new LogicalDevice(childPtr, iedModel);
break;
case 1: case 1:
return new LogicalNode (childPtr); child = new LogicalNode(childPtr, this);
break;
case 2: case 2:
return new DataObject (childPtr); child = new DataObject(childPtr, this);
break;
case 3: case 3:
return new DataAttribute (childPtr); child = new DataAttribute(childPtr, this);
break;
default: default:
return new ModelNode (childPtr); child = new ModelNode(childPtr, this);
break;
}
if (child != null && iedModel != null)
{
iedModel.modelNodes.Add(childPtr, child);
}
}
return child;
}
internal static ModelNode CreateInstance(IntPtr instPtr, ModelNode parent)
{
int nodeType = ModelNode_getType(instPtr);
ModelNode newInstance = null;
switch (nodeType)
{
case 1:
newInstance = new LogicalNode(instPtr, parent);
break;
case 2:
newInstance = new DataObject(instPtr, parent);
break;
case 3:
newInstance = new DataAttribute(instPtr, parent);
break;
default:
newInstance = new ModelNode(instPtr, parent);
break;
}
return newInstance;
}
/// <summary>
/// Gets the direct child nodes of this ModelNode instance
/// </summary>
/// <returns>List of child nodes</returns>
public LinkedList<ModelNode> GetChildren()
{
LinkedList<ModelNode> children = new LinkedList<ModelNode>();
IntPtr childListPtr = ModelNode_getChildren(self);
if (childListPtr != IntPtr.Zero)
{
IedModel iedModel = GetIedModel();
IntPtr listElem = LinkedList_getNext(childListPtr);
while (listElem != IntPtr.Zero)
{
IntPtr modelNodePtr = LinkedList_getData(listElem);
ModelNode childNode = null;
if (iedModel != null)
{
iedModel.modelNodes.TryGetValue(modelNodePtr, out childNode);
}
if (childNode == null)
{
childNode = ModelNode.CreateInstance(modelNodePtr, this);
if ((childNode != null) && (iedModel != null))
{
iedModel.modelNodes.Add(modelNodePtr, childNode);
}
}
if (childNode != null)
children.AddLast(childNode);
listElem = LinkedList_getNext(listElem);
}
LinkedList_destroyStatic(childListPtr);
} }
return children;
} }
/// <summary> /// <summary>
@ -1273,6 +1558,10 @@ namespace IEC61850
static extern void IedServer_handleWriteAccess(IntPtr self, IntPtr dataAttribute, static extern void IedServer_handleWriteAccess(IntPtr self, IntPtr dataAttribute,
InternalWriteAccessHandler handler, IntPtr parameter); InternalWriteAccessHandler handler, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_handleWriteAccessForComplexAttribute(IntPtr self, IntPtr dataAttribute,
InternalWriteAccessHandler handler, IntPtr parameter);
public delegate void ConnectionIndicationHandler(IedServer iedServer, ClientConnection clientConnection, bool connected, object parameter); public delegate void ConnectionIndicationHandler(IedServer iedServer, ClientConnection clientConnection, bool connected, object parameter);
private ConnectionIndicationHandler connectionHandler = null; private ConnectionIndicationHandler connectionHandler = null;
@ -1403,13 +1692,20 @@ namespace IEC61850
{ {
WriteAccessHandlerInfo info; WriteAccessHandlerInfo info;
writeAccessHandlers.TryGetValue (dataAttribute, out info); if (writeAccessHandlers.TryGetValue(dataAttribute, out info) == true)
{
ClientConnection con = null; ClientConnection con = null;
clientConnections.TryGetValue(connection, out con); clientConnections.TryGetValue(connection, out con);
return (int) info.handler (info.dataAttribute, new MmsValue (value), con, info.parameter); MmsValue mmsValue = new MmsValue(value);
return (int)info.handler(info.dataAttribute, mmsValue.Clone(), con, info.parameter);
}
else
{
return (int) MmsDataAccessError.OBJECT_ACCESS_DENIED;
}
} }
private Dictionary<IntPtr, WriteAccessHandlerInfo> writeAccessHandlers = new Dictionary<IntPtr, WriteAccessHandlerInfo> (); private Dictionary<IntPtr, WriteAccessHandlerInfo> writeAccessHandlers = new Dictionary<IntPtr, WriteAccessHandlerInfo> ();
@ -1657,6 +1953,22 @@ namespace IEC61850
IedServer_setSelectStateChangedHandler(self, controlObject.self, internalSelectedStateChangedHandlerRef, GCHandle.ToIntPtr(info.handle)); IedServer_setSelectStateChangedHandler(self, controlObject.self, internalSelectedStateChangedHandlerRef, GCHandle.ToIntPtr(info.handle));
} }
/// <summary>
/// Install a WriteAccessHandler for a data attribute.
/// </summary>
/// This instructs the server to monitor write attempts by MMS clients to specific
/// data attributes.If a client tries to write to the monitored data attribute the
/// handler is invoked.The handler can decide if the write access will be allowed
/// or denied.If a WriteAccessHandler is set for a specific data attribute - the
/// default write access policy will not be performed for that data attribute.
/// <remarks>
/// NOTE: If the data attribute has sub data attributes, the WriteAccessHandler is not
/// set for the sub data attributes and will not be called when the sub data attribute is
/// written directly!
/// </remarks>
/// <param name="dataAttr">the data attribute to monitor</param>
/// <param name="handler">the callback function that is invoked if a client tries to write to the monitored data attribute.</param>
/// <param name="parameter">a user provided parameter that is passed to the WriteAccessHandler when called.</param>
public void HandleWriteAccess (DataAttribute dataAttr, WriteAccessHandler handler, object parameter) public void HandleWriteAccess (DataAttribute dataAttr, WriteAccessHandler handler, object parameter)
{ {
writeAccessHandlers.Add (dataAttr.self, new WriteAccessHandlerInfo(handler, parameter, dataAttr)); writeAccessHandlers.Add (dataAttr.self, new WriteAccessHandlerInfo(handler, parameter, dataAttr));
@ -1664,17 +1976,71 @@ namespace IEC61850
IedServer_handleWriteAccess (self, dataAttr.self, WriteAccessHandlerImpl, IntPtr.Zero); IedServer_handleWriteAccess (self, dataAttr.self, WriteAccessHandlerImpl, IntPtr.Zero);
} }
private void AddHandlerInfoForDataAttributeRecursive(DataAttribute da, WriteAccessHandler handler, object parameter)
{
writeAccessHandlers.Add(da.self, new WriteAccessHandlerInfo(handler, parameter, da));
foreach (ModelNode child in da.GetChildren())
{
if (child is DataAttribute)
{
AddHandlerInfoForDataAttributeRecursive(child as DataAttribute, handler, parameter);
}
}
}
/// <summary>
/// Install a WriteAccessHandler for a data attribute and for all sub data attributes
/// </summary>
/// This instructs the server to monitor write attempts by MMS clients to specific
/// data attributes.If a client tries to write to the monitored data attribute the
/// handler is invoked.The handler can decide if the write access will be allowed
/// or denied.If a WriteAccessHandler is set for a specific data attribute - the
/// default write access policy will not be performed for that data attribute.
/// <remarks>
/// NOTE: When the data attribute is a complex attribute then the handler will also be installed
/// for all sub data attributes. When the data attribute is a basic data attribute then
/// this function behaves like <see cref="HandleWriteAccess"/>.
/// </remarks>
/// <param name="dataAttr">the data attribute to monitor</param>
/// <param name="handler">the callback function that is invoked if a client tries to write to the monitored data attribute.</param>
/// <param name="parameter">a user provided parameter that is passed to the WriteAccessHandler when called.</param>
public void HandleWriteAccessForComplexAttribute(DataAttribute dataAttr, WriteAccessHandler handler, object parameter)
{
AddHandlerInfoForDataAttributeRecursive(dataAttr, handler, parameter);
IedServer_handleWriteAccessForComplexAttribute(self, dataAttr.self, WriteAccessHandlerImpl, IntPtr.Zero);
}
public void SetWriteAccessPolicy(FunctionalConstraint fc, AccessPolicy policy) public void SetWriteAccessPolicy(FunctionalConstraint fc, AccessPolicy policy)
{ {
IedServer_setWriteAccessPolicy (self, fc, policy); IedServer_setWriteAccessPolicy (self, fc, policy);
} }
/// <summary>
/// Locks the data model for data update.
/// </summary>
/// This function should be called before the data model is updated.
/// After updating the data model the function <see cref="UnlockDataModel"/> should be called.
///
/// <remarks>
/// his method should never be called inside of a library callback function. In the context of
/// a library callback the data model is always already locked! Calling this function inside of a
/// library callback may lead to a deadlock condition.
/// </remarks>
public void LockDataModel() public void LockDataModel()
{ {
IedServer_lockDataModel(self); IedServer_lockDataModel(self);
} }
/// <summary>
/// Unlocks the data model and process pending client requests.
/// </summary>
///
/// <remarks>
/// This method should never be called inside of a library callback function. In the context of
/// a library callback the data model is always already locked!
/// </remarks>
public void UnlockDataModel() public void UnlockDataModel()
{ {
IedServer_unlockDataModel(self); IedServer_unlockDataModel(self);

@ -244,6 +244,8 @@ namespace tests
Assert.AreEqual (list.ToArray () [0], "simpleIOGenericIO"); Assert.AreEqual (list.ToArray () [0], "simpleIOGenericIO");
Assert.IsTrue(iedServer.IsRunning());
iedServer.Stop (); iedServer.Stop ();
iedServer.Destroy (); iedServer.Destroy ();
@ -289,6 +291,34 @@ namespace tests
Assert.IsNotNull (modelNode); Assert.IsNotNull (modelNode);
} }
[Test()]
public void AccessDataModelServerSideNavigateModelNode()
{
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("../../model.cfg");
ModelNode modelNode = iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.AnIn1");
Assert.IsNotNull(modelNode);
Assert.IsTrue(modelNode.GetType().Equals(typeof(DataObject)));
var children = modelNode.GetChildren();
Assert.AreEqual(3, children.Count);
ModelNode mag = children.First.Value;
Assert.AreEqual("mag", mag.GetName());
ModelNode t = children.Last.Value;
Assert.AreEqual("t", t.GetName());
//modelNode = iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.AnIn1.mag.f");
//Assert.IsTrue(modelNode.GetType().Equals(typeof(IEC61850.Server.DataAttribute)));
}
[Test ()] [Test ()]
public void AccessDataModelClientServer() public void AccessDataModelClientServer()
{ {
@ -383,9 +413,61 @@ namespace tests
} }
[Test()] [Test()]
public void WriteAccessPolicy() public void ControlWriteAccessComplexDAToServer()
{ {
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("../../model2.cfg");
IEC61850.Server.DataAttribute setAnVal_setMag = (IEC61850.Server.DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/LLN0.SetAnVal.setMag");
IedServer iedServer = new IedServer(iedModel);
int handlerCalled = 0;
MmsValue receivedValue = null;
iedServer.SetWriteAccessPolicy(FunctionalConstraint.SP, AccessPolicy.ACCESS_POLICY_DENY);
iedServer.HandleWriteAccessForComplexAttribute(setAnVal_setMag, delegate (IEC61850.Server.DataAttribute dataAttr, MmsValue value, ClientConnection con, object parameter) {
receivedValue = value;
handlerCalled++;
return MmsDataAccessError.SUCCESS;
}, null);
iedServer.Start(10002);
IedConnection connection = new IedConnection();
connection.Connect("localhost", 10002);
MmsValue complexValue = MmsValue.NewEmptyStructure(1);
complexValue.SetElement(0, new MmsValue((float)1.0));
connection.WriteValue("simpleIOGenericIO/LLN0.SetAnVal.setMag", FunctionalConstraint.SP, complexValue);
Assert.NotNull(receivedValue);
Assert.AreEqual(MmsType.MMS_STRUCTURE, receivedValue.GetType());
Assert.AreEqual(1.0, receivedValue.GetElement(0).ToFloat());
receivedValue.Dispose();
receivedValue = null;
connection.WriteValue("simpleIOGenericIO/LLN0.SetAnVal.setMag.f", FunctionalConstraint.SP, new MmsValue((float)2.0));
Assert.NotNull(receivedValue);
Assert.AreEqual(MmsType.MMS_FLOAT, receivedValue.GetType());
Assert.AreEqual(2.0, receivedValue.ToFloat());
connection.Abort();
iedServer.Stop();
iedServer.Dispose();
}
[Test()]
public void WriteAccessPolicy()
{
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("../../model.cfg"); IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("../../model.cfg");
IEC61850.Server.DataAttribute opDlTmms = (IEC61850.Server.DataAttribute) iedModel.GetModelNodeByShortObjectReference("GenericIO/PDUP1.OpDlTmms.setVal"); IEC61850.Server.DataAttribute opDlTmms = (IEC61850.Server.DataAttribute) iedModel.GetModelNodeByShortObjectReference("GenericIO/PDUP1.OpDlTmms.setVal");
@ -404,6 +486,8 @@ namespace tests
connection.Connect ("localhost", 10002); connection.Connect ("localhost", 10002);
iedServer.SetWriteAccessPolicy(FunctionalConstraint.SP, AccessPolicy.ACCESS_POLICY_ALLOW);
connection.WriteValue ("simpleIOGenericIO/PDUP1.RsDlTmms.setVal", FunctionalConstraint.SP, new MmsValue ((int)1234)); connection.WriteValue ("simpleIOGenericIO/PDUP1.RsDlTmms.setVal", FunctionalConstraint.SP, new MmsValue ((int)1234));
iedServer.SetWriteAccessPolicy (FunctionalConstraint.SP, AccessPolicy.ACCESS_POLICY_DENY); iedServer.SetWriteAccessPolicy (FunctionalConstraint.SP, AccessPolicy.ACCESS_POLICY_DENY);
@ -425,11 +509,10 @@ namespace tests
iedServer.Stop (); iedServer.Stop ();
iedServer.Destroy (); iedServer.Dispose();
} }
[Test()] [Test()]
[Ignore("has to be fixed")]
public void ControlHandler() public void ControlHandler()
{ {
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("../../model.cfg"); IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("../../model.cfg");
@ -476,7 +559,7 @@ namespace tests
iedServer.Stop (); iedServer.Stop ();
iedServer.Destroy (); iedServer.Dispose();
} }
@ -525,6 +608,8 @@ namespace tests
Assert.AreEqual ("127.0.0.1:", ipAddress.Substring (0, 10)); Assert.AreEqual ("127.0.0.1:", ipAddress.Substring (0, 10));
iedServer.Stop (); iedServer.Stop ();
iedServer.Dispose();
} }
[Test()] [Test()]
@ -555,7 +640,7 @@ namespace tests
} }
[Test()] [Test()]
public void MmsValaueCreateStructureAndAddElement() public void MmsValueCreateStructureAndAddElement()
{ {
MmsValue structure1 = MmsValue.NewEmptyStructure(1); MmsValue structure1 = MmsValue.NewEmptyStructure(1);
MmsValue structure2 = MmsValue.NewEmptyStructure(1); MmsValue structure2 = MmsValue.NewEmptyStructure(1);

@ -0,0 +1,446 @@
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);
}
DO(SetInt1 0){
DA(setVal 0 3 2 1 0);
}
DO(SetInt2 0){
DA(setVal 0 3 2 1 0);
}
DO(SetInt3 0){
DA(setVal 0 3 2 1 0);
}
DO(SetInt4 0){
DA(setVal 0 3 2 1 0);
}
DO(SetBool1 0){
DA(setVal 0 0 2 1 0);
}
DO(SetBool2 0){
DA(setVal 0 0 2 1 0);
}
DO(SetBool3 0){
DA(setVal 0 0 2 1 0);
}
DO(SetBool4 0){
DA(setVal 0 0 2 1 0);
}
DO(Int64 0){
DA(stVal 0 4 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(SetAnVal 0){
DA(setMag 0 27 2 1 0){
DA(f 0 10 2 1 0);
}
}
DS(Events){
DE(GGIO1$ST$SPCSO1$stVal);
DE(GGIO1$ST$SPCSO2$stVal);
DE(GGIO1$ST$SPCSO3$stVal);
DE(GGIO1$ST$SPCSO4$stVal);
}
DS(EventsFCDO){
DE(GGIO1$ST$SPCSO1);
DE(GGIO1$ST$SPCSO2);
DE(GGIO1$ST$SPCSO3);
DE(GGIO1$ST$SPCSO4);
}
DS(Booleans){
DE(LLN0$SP$SetBool1$setVal);
DE(LLN0$SP$SetBool2$setVal);
DE(LLN0$SP$SetBool3$setVal);
DE(LLN0$SP$SetBool4$setVal);
}
DS(Integers){
DE(LLN01$SP$SetInt1$setVal);
DE(LLN01$SP$SetInt2$setVal);
DE(LLN01$SP$SetInt3$setVal);
DE(LLN01$SP$SetInt4$setVal);
}
RC(EventsRCB01 Events1 0 Events 1 24 239 50 1000);
RC(EventsRCB02 Events1 0 Events 1 24 239 50 1000);
RC(BufferedRCB01 Events1 1 Events 1 24 239 50 1000);
RC(BufferedRCB02 Events1 1 Events 1 24 239 50 1000);
GC(gcbEvents events Events 1 0 1000 3000 ){
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);
DA(dU 0 21 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(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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=1;
}
DO(SPCSO2 0){
DA(SBO 0 17 12 0 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(Cancel 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=2;
DA(sboClass 0 12 4 0 0);
}
DO(SPCSO3 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(Cancel 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=3;
}
DO(SPCSO4 0){
DA(SBOw 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(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(Cancel 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=4;
}
DO(SPCSO5 0){
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=1;
DA(Cancel 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);
}
}
DO(SPCSO6 0){
DA(SBO 0 17 12 0 0);
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Cancel 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=2;
}
DO(SPCSO7 0){
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Cancel 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=3;
}
DO(SPCSO8 0){
DA(SBOw 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(Cancel 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(operTm 0 22 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(origin 0 27 0 0 0){
DA(orCat 0 12 0 0 0);
DA(orIdent 0 13 0 0 0);
}
DA(ctlNum 0 6 0 0 0);
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=4;
}
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);
}
DO(SchdAbsTm 0){
DA(val 24 10 2 1 0);
}
}
LN(MHAI1){
DO(HA 0){
DO(phsAHar 16){
DA(cVal 0 27 1 5 0){
DA(mag 0 27 1 5 0){
DA(f 0 10 1 5 0);
}
DA(ang 0 27 1 5 0){
DA(f 0 10 1 5 0);
}
}
DA(q 0 23 1 2 0);
DA(t 0 22 1 0 0);
}
DA(numHar 0 7 4 1 0)=16;
DA(numCyc 0 7 4 1 0);
DA(evalTm 0 7 4 1 0);
DA(frequency 0 10 4 1 0);
}
}
}
}

@ -0,0 +1,430 @@
<?xml version="1.0" encoding="UTF-8"?>
<SCL xmlns="http://www.iec.ch/61850/2003/SCL">
<Header id="" version="4.0.2" revision="" toolID="" nameStructure="IEDName">
</Header>
<Communication>
<SubNetwork name="subnetwork1" type="8-MMS">
<Text>Station bus</Text>
<BitRate unit="b/s">10</BitRate>
<ConnectedAP iedName="simpleIO" apName="accessPoint1">
<Address>
<P type="IP">10.0.0.2</P>
<P type="IP-SUBNET">255.255.255.0</P>
<P type="IP-GATEWAY">10.0.0.1</P>
<P type="OSI-TSEL">0001</P>
<P type="OSI-PSEL">00000001</P>
<P type="OSI-SSEL">0001</P>
</Address>
<GSE ldInst="GenericIO" cbName="gcbEvents">
<Address>
<P type="VLAN-ID">1</P>
<P type="VLAN-PRIORITY">4</P>
<P type="MAC-Address">01-0c-cd-01-00-01</P>
<P type="APPID">1000</P>
</Address>
<MinTime>1000</MinTime>
<MaxTime>3000</MaxTime>
</GSE>
</ConnectedAP>
</SubNetwork>
</Communication>
<IED name="simpleIO">
<Services>
<DynAssociation />
<GetDirectory />
<GetDataObjectDefinition />
<GetDataSetValue />
<DataSetDirectory />
<ReadWrite />
<GetCBValues />
<ConfLNs fixPrefix="true" fixLnInst="true" />
<GOOSE max="5" />
<GSSE max="5" />
<FileHandling />
<GSEDir />
<TimerActivatedControl />
</Services>
<AccessPoint name="accessPoint1">
<Server>
<Authentication />
<LDevice inst="GenericIO">
<LN0 lnClass="LLN0" lnType="LLN01" inst="">
<DataSet name="Events" desc="Events">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" daName="stVal" />
</DataSet>
<DataSet name="EventsFCDO" desc="EventsFCDO">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1"/>
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2"/>
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3"/>
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4"/>
</DataSet>
<DataSet name="Booleans" desc="Booleans">
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" doName="SetBool1" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" doName="SetBool2" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" doName="SetBool3" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" doName="SetBool4" daName="setVal" />
</DataSet>
<DataSet name="Integers" desc="Integers">
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" lnInst="1" doName="SetInt1" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" lnInst="1" doName="SetInt2" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" lnInst="1" doName="SetInt3" daName="setVal" />
<FCDA ldInst="GenericIO" lnClass="LLN0" fc="SP" lnInst="1" doName="SetInt4" daName="setVal" />
</DataSet>
<ReportControl name="EventsRCB" confRev="1" datSet="Events" rptID="Events1" buffered="false" intgPd="1000" bufTime="50" indexed="true">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="2" />
</ReportControl>
<ReportControl name="BufferedRCB" confRev="1" datSet="Events" rptID="Events1" buffered="true" intgPd="1000" bufTime="50" indexed="true">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="2" />
</ReportControl>
<GSEControl appID="events" name="gcbEvents" type="GOOSE" datSet="Events" confRev="1"/>
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</Val>
</DAI>
</DOI>
</LN0>
<LN lnClass="LPHD" lnType="LPHD1" inst="1" prefix="" />
<LN lnClass="GGIO" lnType="GGIO1" inst="1" prefix="">
<DOI name="Mod">
<DAI name="ctlModel">
<Val>status-only</Val>
</DAI>
</DOI>
<DOI name="SPCSO1">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO2">
<DAI name="ctlModel">
<Val>sbo-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO3">
<DAI name="ctlModel">
<Val>direct-with-enhanced-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO4">
<DAI name="ctlModel">
<Val>sbo-with-enhanced-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO5">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO6">
<DAI name="ctlModel">
<Val>sbo-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO7">
<DAI name="ctlModel">
<Val>direct-with-enhanced-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO8">
<DAI name="ctlModel">
<Val>sbo-with-enhanced-security</Val>
</DAI>
</DOI>
</LN>
<LN lnClass="MHAI" lnType="MHAI1" inst="1" prefix="">
<DOI name="HA">
<DAI name="numHar">
<Val>16</Val>
</DAI>
</DOI>
</LN>
</LDevice>
</Server>
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType id="LLN01" lnClass="LLN0">
<DO name="Mod" type="INC_1_Mod" />
<DO name="Beh" type="INS_1_Beh" />
<DO name="Health" type="INS_1_Beh" />
<DO name="NamPlt" type="LPL_1_NamPlt" />
<DO name="SetInt1" type="ISP" />
<DO name="SetInt2" type="ISP" />
<DO name="SetInt3" type="ISP" />
<DO name="SetInt4" type="ISP" />
<DO name="SetBool1" type="SPG_1" />
<DO name="SetBool2" type="SPG_1" />
<DO name="SetBool3" type="SPG_1" />
<DO name="SetBool4" type="SPG_1" />
<DO name="Int64" type="INS_64" />
<DO name="SetAnVal" type="ASG" />
</LNodeType>
<LNodeType id="LPHD1" lnClass="LPHD">
<DO name="PhyNam" type="DPL_1_PhyNam" />
<DO name="PhyHealth" type="INS_1_Beh" />
<DO name="Proxy" type="SPS_1_Proxy" />
</LNodeType>
<LNodeType id="GGIO1" lnClass="GGIO">
<DO name="Mod" type="INC_1_Mod" />
<DO name="Beh" type="INS_1_Beh" />
<DO name="Health" type="INS_1_Beh" />
<DO name="NamPlt" type="LPL_2_NamPlt" />
<DO name="AnIn1" type="MV_1_AnIn1" />
<DO name="AnIn2" type="MV_1_AnIn1" />
<DO name="AnIn3" type="MV_1_AnIn1" />
<DO name="AnIn4" type="MV_1_AnIn1" />
<DO name="SPCSO1" type="SPC_1_SPCSO1" />
<DO name="SPCSO2" type="SPC_1_SPCSO2" />
<DO name="SPCSO3" type="SPC_1_SPCSO3" />
<DO name="SPCSO4" type="SPC_1_SPCSO4" />
<DO name="SPCSO5" type="SPC_1_SPCSO5" />
<DO name="SPCSO6" type="SPC_1_SPCSO6" />
<DO name="SPCSO7" type="SPC_1_SPCSO7" />
<DO name="SPCSO8" type="SPC_1_SPCSO8" />
<DO name="Ind1" type="SPS_1_Proxy" />
<DO name="Ind2" type="SPS_1_Proxy" />
<DO name="Ind3" type="SPS_1_Proxy" />
<DO name="Ind4" type="SPS_1_Proxy" />
<DO name="SchdAbsTm" type="SCA_1_SchdAbsTm" />
</LNodeType>
<LNodeType id="MHAI1" lnClass="MHAI">
<DO name="HA" type="HWYE_1_HA" />
</LNodeType>
<DOType id="SPG_1" cdc="SPG">
<DA name="setVal" bType="BOOLEAN" fc="SP" dchg="true" />
</DOType>
<DOType id="ASG" cdc="ASG">
<DA name="setMag" bType="Struct" type="AnalogueValue" fc="SP" dchg="true" />
</DOType>
<DOType id="ISP" cdc="INS">
<DA name="setVal" bType="INT32" fc="SP" dchg="true" />
</DOType>
<DOType id="HWYE_1_HA" cdc="HWYE">
<SDO name="phsAHar" type="CMV_1_phsAHar" count="16" />
<DA name="numHar" bType="INT16U" fc="CF" dchg="true" />
<DA name="numCyc" bType="INT16U" fc="CF" dchg="true" />
<DA name="evalTm" bType="INT16U" fc="CF" dchg="true" />
<DA name="frequency" bType="FLOAT32" fc="CF" dchg="true" />
</DOType>
<DOType id="SCA_1_SchdAbsTm" cdc="SCA">
<DA name="val" bType="FLOAT32" count="24" fc="SP" dchg="true" />
</DOType>
<DOType id="CMV_1_phsAHar" cdc="CMV">
<DA name="cVal" bType="Struct" type="Vector" fc="MX" dchg="true" dupd="true" />
<DA name="q" bType="Quality" fc="MX" qchg="true" />
<DA name="t" bType="Timestamp" fc="MX" />
</DOType>
<DAType id="Vector">
<BDA name="mag" bType="Struct" type="AnalogueValue" /> <!-- M -->
<BDA name="ang" bType="Struct" type="AnalogueValue" /> <!-- O -->
</DAType>
<DOType id="INC_1_Mod" cdc="INC">
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="INS_1_Beh" cdc="INS">
<DA name="stVal" bType="INT32" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="INS_64" cdc="INS">
<DA name="stVal" bType="INT64" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="LPL_1_NamPlt" cdc="LPL">
<DA name="vendor" bType="VisString255" fc="DC" />
<DA name="swRev" bType="VisString255" fc="DC" />
<DA name="d" bType="VisString255" fc="DC" />
<DA name="configRev" bType="VisString255" fc="DC" />
<DA name="ldNs" bType="VisString255" fc="EX" />
</DOType>
<DOType id="DPL_1_PhyNam" cdc="DPL">
<DA name="vendor" bType="VisString255" fc="DC" />
</DOType>
<DOType id="SPS_1_Proxy" cdc="SPS">
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="SPC_1_SPCSO8" cdc="SPC">
<DA name="SBOw" type="SPCOperate_5" bType="Struct" fc="CO" />
<DA name="Oper" type="SPCOperate_5" bType="Struct" fc="CO" />
<DA name="Cancel" type="SPCCancel_5" bType="Struct" fc="CO" />
<DA name="origin" type="Originator_1" bType="Struct" fc="ST" />
<DA name="ctlNum" bType="INT8U" fc="ST" />
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="SPC_1_SPCSO7" cdc="SPC">
<DA name="Oper" type="SPCOperate_5" bType="Struct" fc="CO" />
<DA name="Cancel" type="SPCCancel_5" bType="Struct" fc="CO" />
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="SPC_1_SPCSO3" cdc="SPC">
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="Cancel" type="SPCCancel_1" bType="Struct" fc="CO" />
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="MV_1_AnIn1" cdc="MV">
<DA name="mag" type="" bType="Struct" fc="MX" dchg="true" />
<DA name="q" bType="Quality" fc="MX" qchg="true" />
<DA name="t" bType="Timestamp" fc="MX" />
</DOType>
<DOType id="SPC_1_SPCSO6" cdc="SPC">
<DA name="SBO" bType="VisString64" fc="CO" />
<DA name="Oper" type="SPCOperate_5" bType="Struct" fc="CO" />
<DA name="Cancel" type="SPCCancel_5" bType="Struct" fc="CO" />
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="SPC_1_SPCSO5" cdc="SPC">
<DA name="Oper" type="SPCOperate_5" bType="Struct" fc="CO" />
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
<DA name="Cancel" type="SPCCancel_1" bType="Struct" fc="CO" />
</DOType>
<DOType id="SPC_1_SPCSO4" cdc="SPC">
<DA name="SBOw" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="Cancel" type="SPCCancel_1" bType="Struct" fc="CO" />
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="LPL_2_NamPlt" cdc="LPL">
<DA name="vendor" bType="VisString255" fc="DC" />
<DA name="swRev" bType="VisString255" fc="DC" />
<DA name="d" bType="VisString255" fc="DC" />
<DA name="dU" fc="DC" bType="Unicode255"/>
</DOType>
<DOType id="SPC_1_SPCSO2" cdc="SPC">
<DA name="SBO" bType="VisString64" fc="CO" />
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="Cancel" type="SPCCancel_1" bType="Struct" fc="CO" />
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
<DA name="sboClass" type="SboClasses" bType="Enum" fc="CF" />
</DOType>
<DOType id="SPC_1_SPCSO1" cdc="SPC">
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DAType id="SPCOperate_1">
<BDA name="ctlVal" bType="BOOLEAN" />
<BDA name="origin" type="Originator_1" bType="Struct" />
<BDA name="ctlNum" bType="INT8U" />
<BDA name="T" bType="Timestamp" />
<BDA name="Test" bType="BOOLEAN" />
<BDA name="Check" bType="Check" />
</DAType>
<DAType id="Originator_1">
<BDA name="orCat" type="OrCat" bType="Enum" />
<BDA name="orIdent" bType="Octet64" />
</DAType>
<DAType id="SPCOperate_5">
<BDA name="ctlVal" bType="BOOLEAN" />
<BDA name="operTm" bType="Timestamp" />
<BDA name="origin" type="Originator_1" bType="Struct" />
<BDA name="ctlNum" bType="INT8U" />
<BDA name="T" bType="Timestamp" />
<BDA name="Test" bType="BOOLEAN" />
<BDA name="Check" bType="Check" />
</DAType>
<DAType id="">
<BDA name="f" bType="FLOAT32" />
</DAType>
<DAType id="SPCCancel_1">
<BDA name="ctlVal" bType="BOOLEAN" />
<BDA name="origin" type="Originator_1" bType="Struct" />
<BDA name="ctlNum" bType="INT8U" />
<BDA name="T" bType="Timestamp" />
<BDA name="Test" bType="BOOLEAN" />
</DAType>
<DAType id="SPCCancel_5">
<BDA name="ctlVal" bType="BOOLEAN" />
<BDA name="operTm" bType="Timestamp" />
<BDA name="origin" type="Originator_1" bType="Struct" />
<BDA name="ctlNum" bType="INT8U" />
<BDA name="T" bType="Timestamp" />
<BDA name="Test" bType="BOOLEAN" />
</DAType>
<DAType id="AnalogueValue"><!-- sec 6.3 -->
<!--<BDA name="i" bType="INT32" /> --><!-- GC_1 -->
<BDA name="f" bType="FLOAT32" /><!-- GC_1 -->
</DAType>
<EnumType id="CtlModels">
<EnumVal ord="0">status-only</EnumVal>
<EnumVal ord="1">direct-with-normal-security</EnumVal>
<EnumVal ord="2">sbo-with-normal-security</EnumVal>
<EnumVal ord="3">direct-with-enhanced-security</EnumVal>
<EnumVal ord="4">sbo-with-enhanced-security</EnumVal>
</EnumType>
<EnumType id="SboClasses">
<EnumVal ord="0">operate-once</EnumVal>
<EnumVal ord="1">operate-many</EnumVal>
</EnumType>
<EnumType id="OrCat">
<EnumVal ord="0">not-supported</EnumVal>
<EnumVal ord="1">bay-control</EnumVal>
<EnumVal ord="2">station-control</EnumVal>
<EnumVal ord="3">remote-control</EnumVal>
<EnumVal ord="4">automatic-bay</EnumVal>
<EnumVal ord="5">automatic-station</EnumVal>
<EnumVal ord="6">automatic-remote</EnumVal>
<EnumVal ord="7">maintenance</EnumVal>
<EnumVal ord="8">process</EnumVal>
</EnumType>
</DataTypeTemplates>
</SCL>
Loading…
Cancel
Save