- .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;
}
/* cache managed ModelNode instances of the IedModel */
internal Dictionary<IntPtr, ModelNode> modelNodes = new Dictionary<IntPtr, ModelNode>();
/// <summary>
/// Initializes a new instance of the <see cref="T:IEC61850.Server.IedModel"/> class.
/// </summary>
@ -132,26 +135,112 @@ namespace IEC61850
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);
switch (nodeType) {
case 0:
return new LogicalDevice (nodeRef);
if (nodeType == 0)
{
modelNode = new LogicalDevice(nodeRef, this);
}
else
{
ModelNode parent = GetParent(nodeRef);
if (parent != null)
{
switch (nodeType)
{
case 1:
return new LogicalNode (nodeRef);
modelNode = new LogicalNode(nodeRef, parent);
break;
case 2:
return new DataObject (nodeRef);
modelNode = new DataObject(nodeRef, parent);
break;
case 3:
return new DataAttribute (nodeRef);
modelNode = new DataAttribute(nodeRef, parent);
break;
default:
return new ModelNode (nodeRef);
modelNode = new ModelNode(nodeRef, parent);
break;
}
}
}
if (modelNode != null)
{
modelNodes.Add(nodeRef, modelNode);
}
}
return modelNode;
}
/// <summary>
@ -175,7 +264,7 @@ namespace IEC61850
if (nodeRef == IntPtr.Zero)
return null;
return getModelNodeFromNodeRef (nodeRef);
return GetModelNodeFromNodeRef (nodeRef);
}
/// <summary>
@ -190,7 +279,7 @@ namespace IEC61850
if (nodeRef == IntPtr.Zero)
return null;
return getModelNodeFromNodeRef (nodeRef);
return GetModelNodeFromNodeRef (nodeRef);
}
}
@ -200,12 +289,19 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
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)
{
this.iedModel = parent;
self = LogicalDevice_create(name, parent.self);
}
}
@ -215,12 +311,15 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
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)
{
this.parent = parent;
base.self = LogicalNode_create(name, parent.self);
}
}
@ -411,7 +510,7 @@ namespace IEC61850
IntPtr self = CDC_SPS_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject (self);
return new DataObject (self, parent);
else
return null;
}
@ -421,7 +520,7 @@ namespace IEC61850
IntPtr self = CDC_DPS_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -431,7 +530,7 @@ namespace IEC61850
IntPtr self = CDC_VSS_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -441,7 +540,7 @@ namespace IEC61850
IntPtr self = CDC_SEC_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -451,7 +550,7 @@ namespace IEC61850
IntPtr self = CDC_CMV_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -461,7 +560,7 @@ namespace IEC61850
IntPtr self = CDC_SAV_create(name, parent.self, options, isIntegerNotFloat);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -471,7 +570,7 @@ namespace IEC61850
IntPtr self = CDC_ACD_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -481,7 +580,7 @@ namespace IEC61850
IntPtr self = CDC_ACT_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -491,7 +590,7 @@ namespace IEC61850
IntPtr self = CDC_SPG_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -501,7 +600,7 @@ namespace IEC61850
IntPtr self = CDC_VSG_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -511,7 +610,7 @@ namespace IEC61850
IntPtr self = CDC_ENG_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -521,7 +620,7 @@ namespace IEC61850
IntPtr self = CDC_ING_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -531,7 +630,7 @@ namespace IEC61850
IntPtr self = CDC_ASG_create(name, parent.self, options, isIntegerNotFloat);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -541,7 +640,7 @@ namespace IEC61850
IntPtr self = CDC_WYE_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -551,7 +650,7 @@ namespace IEC61850
IntPtr self = CDC_DEL_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -561,7 +660,7 @@ namespace IEC61850
IntPtr self = CDC_HST_create(name, parent.self, options, maxPts);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -571,7 +670,7 @@ namespace IEC61850
IntPtr self = CDC_INS_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject (self);
return new DataObject (self, parent);
else
return null;
}
@ -581,7 +680,7 @@ namespace IEC61850
IntPtr self = CDC_MV_create(name, parent.self, options, isIntegerNotFloat);
if (self != IntPtr.Zero)
return new DataObject (self);
return new DataObject (self, parent);
else
return null;
}
@ -591,7 +690,7 @@ namespace IEC61850
IntPtr self = CDC_INC_create(name, parent.self, options, controlOptions);
if (self != IntPtr.Zero)
return new DataObject (self);
return new DataObject (self, parent);
else
return null;
}
@ -601,7 +700,7 @@ namespace IEC61850
IntPtr self = CDC_LPL_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject (self);
return new DataObject (self, parent);
else
return null;
}
@ -611,7 +710,7 @@ namespace IEC61850
IntPtr self = CDC_DPL_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject (self);
return new DataObject (self, parent);
else
return null;
}
@ -621,7 +720,7 @@ namespace IEC61850
IntPtr self = CDC_ENS_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -631,7 +730,7 @@ namespace IEC61850
IntPtr self = CDC_SPC_create(name, parent.self, options, controlOptions);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -641,7 +740,7 @@ namespace IEC61850
IntPtr self = CDC_DPC_create(name, parent.self, options, controlOptions);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -651,7 +750,7 @@ namespace IEC61850
IntPtr self = CDC_BSC_create(name, parent.self, options, controlOptions, hasTransientIndicator);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -661,7 +760,7 @@ namespace IEC61850
IntPtr self = CDC_APC_create(name, parent.self, options, controlOptions, isIntegerNotFloat);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -671,7 +770,7 @@ namespace IEC61850
IntPtr self = CDC_BCR_create(name, parent.self, options);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -681,7 +780,7 @@ namespace IEC61850
IntPtr self = CDC_ENC_create(name, parent.self, options, controlOptions);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -691,7 +790,7 @@ namespace IEC61850
IntPtr self = CDC_SPV_create(name, parent.self, options, controlOptions, wpOptions, hasChaManRs);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -701,7 +800,7 @@ namespace IEC61850
IntPtr self = CDC_STV_create(name, parent.self, options, controlOptions, wpOptions, hasOldStatus);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -711,7 +810,7 @@ namespace IEC61850
IntPtr self = CDC_CMD_create(name, parent.self, options, controlOptions, wpOptions, hasOldStatus, hasCmTm, hasCmCt);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -721,7 +820,7 @@ namespace IEC61850
IntPtr self = CDC_ALM_create(name, parent.self, options, controlOptions, wpOptions, hasOldStatus);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -731,7 +830,7 @@ namespace IEC61850
IntPtr self = CDC_CTE_create(name, parent.self, options, controlOptions, wpOptions, hasHisRs);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -741,7 +840,7 @@ namespace IEC61850
IntPtr self = CDC_TMS_create(name, parent.self, options, controlOptions, wpOptions, hasHisRs);
if (self != IntPtr.Zero)
return new DataObject(self);
return new DataObject(self, parent);
else
return null;
}
@ -752,8 +851,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
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)
@ -762,6 +862,8 @@ namespace IEC61850
public DataObject(string name, ModelNode parent, int arrayElements)
{
this.parent = parent;
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,
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,
int arrayElements, UInt32 sAddr)
{
this.parent = parent;
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)]
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;
internal ModelNode parent = null;
static internal IntPtr GetNativeParent(IntPtr self)
{
return ModelNode_getParent(self);
}
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;
}
/// <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)
{
IntPtr childPtr = ModelNode_getChild(self, name);
@ -818,25 +1001,127 @@ namespace IEC61850
if (childPtr == IntPtr.Zero)
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);
switch (nodeType) {
switch (nodeType)
{
case 0:
return new LogicalDevice (childPtr);
child = new LogicalDevice(childPtr, iedModel);
break;
case 1:
return new LogicalNode (childPtr);
child = new LogicalNode(childPtr, this);
break;
case 2:
return new DataObject (childPtr);
child = new DataObject(childPtr, this);
break;
case 3:
return new DataAttribute (childPtr);
child = new DataAttribute(childPtr, this);
break;
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>
@ -1273,6 +1558,10 @@ namespace IEC61850
static extern void IedServer_handleWriteAccess(IntPtr self, IntPtr dataAttribute,
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);
private ConnectionIndicationHandler connectionHandler = null;
@ -1403,13 +1692,20 @@ namespace IEC61850
{
WriteAccessHandlerInfo info;
writeAccessHandlers.TryGetValue (dataAttribute, out info);
if (writeAccessHandlers.TryGetValue(dataAttribute, out info) == true)
{
ClientConnection con = null;
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> ();
@ -1657,6 +1953,22 @@ namespace IEC61850
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)
{
writeAccessHandlers.Add (dataAttr.self, new WriteAccessHandlerInfo(handler, parameter, dataAttr));
@ -1664,17 +1976,71 @@ namespace IEC61850
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)
{
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()
{
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()
{
IedServer_unlockDataModel(self);

@ -244,6 +244,8 @@ namespace tests
Assert.AreEqual (list.ToArray () [0], "simpleIOGenericIO");
Assert.IsTrue(iedServer.IsRunning());
iedServer.Stop ();
iedServer.Destroy ();
@ -289,6 +291,34 @@ namespace tests
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 ()]
public void AccessDataModelClientServer()
{
@ -383,9 +413,61 @@ namespace tests
}
[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");
IEC61850.Server.DataAttribute opDlTmms = (IEC61850.Server.DataAttribute) iedModel.GetModelNodeByShortObjectReference("GenericIO/PDUP1.OpDlTmms.setVal");
@ -404,6 +486,8 @@ namespace tests
connection.Connect ("localhost", 10002);
iedServer.SetWriteAccessPolicy(FunctionalConstraint.SP, AccessPolicy.ACCESS_POLICY_ALLOW);
connection.WriteValue ("simpleIOGenericIO/PDUP1.RsDlTmms.setVal", FunctionalConstraint.SP, new MmsValue ((int)1234));
iedServer.SetWriteAccessPolicy (FunctionalConstraint.SP, AccessPolicy.ACCESS_POLICY_DENY);
@ -425,11 +509,10 @@ namespace tests
iedServer.Stop ();
iedServer.Destroy ();
iedServer.Dispose();
}
[Test()]
[Ignore("has to be fixed")]
public void ControlHandler()
{
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("../../model.cfg");
@ -476,7 +559,7 @@ namespace tests
iedServer.Stop ();
iedServer.Destroy ();
iedServer.Dispose();
}
@ -525,6 +608,8 @@ namespace tests
Assert.AreEqual ("127.0.0.1:", ipAddress.Substring (0, 10));
iedServer.Stop ();
iedServer.Dispose();
}
[Test()]
@ -555,7 +640,7 @@ namespace tests
}
[Test()]
public void MmsValaueCreateStructureAndAddElement()
public void MmsValueCreateStructureAndAddElement()
{
MmsValue structure1 = 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