コード例 #1
0
        /// <summary>
        /// Creates a new object type.
        /// </summary>
        private BaseObjectTypeState CreateObjectType(NodeState parent, IDictionary <NodeId, IList <IReference> > externalReferences, string path, string name)
        {
            BaseObjectTypeState type = new BaseObjectTypeState();

            type.SymbolicName  = name;
            type.SuperTypeId   = ObjectTypeIds.BaseObjectType;
            type.NodeId        = new NodeId(path, NamespaceIndex);
            type.BrowseName    = new QualifiedName(name, NamespaceIndex);
            type.DisplayName   = type.BrowseName.Name;
            type.WriteMask     = AttributeWriteMask.None;
            type.UserWriteMask = AttributeWriteMask.None;
            type.IsAbstract    = false;

            IList <IReference> references = null;

            if (!externalReferences.TryGetValue(ObjectTypeIds.BaseObjectType, out references))
            {
                externalReferences[ObjectTypeIds.BaseObjectType] = references = new List <IReference>();
            }

            references.Add(new NodeStateReference(ReferenceTypes.HasSubtype, false, type.NodeId));

            if (parent != null)
            {
                parent.AddReference(ReferenceTypes.Organizes, false, type.NodeId);
                type.AddReference(ReferenceTypes.Organizes, true, parent.NodeId);
            }

            AddPredefinedNode(SystemContext, type);
            return(type);
        }
コード例 #2
0
        /// <summary>
        /// Updates the event types in cache with the most recent info fetched from the AE server.
        /// </summary>
        public void UpdateCache(ServerSystemContext context, ushort namespaceIndex)
        {
            // clear the existing nodes.
            EventTypeNodes = new NodeIdDictionary <BaseObjectTypeState>();
            Attributes     = new Dictionary <int, int[]>();
            TypeTable typeTable = context.TypeTable as TypeTable;

            // rebuild from the recently fetched list.
            for (int ii = 0; ii < EventTypes.Count; ii++)
            {
                // save the attributes for use when creating filters.
                if (EventTypes[ii].EventTypeMapping != EventTypeMapping.ConditionClassType && !Attributes.ContainsKey(EventTypes[ii].CategoryId))
                {
                    EventType eventType = EventTypes[ii];

                    int[] attributeIds = new int[eventType.Attributes.Count];

                    for (int jj = 0; jj < attributeIds.Length; jj++)
                    {
                        attributeIds[jj] = eventType.Attributes[jj].Id;
                    }

                    Attributes.Add(EventTypes[ii].CategoryId, attributeIds);
                }

                AeEventTypeState node = new AeEventTypeState(EventTypes[ii], namespaceIndex);

                BaseObjectTypeState mappingNode = null;

                if (!EventTypeNodes.TryGetValue(node.SuperTypeId, out mappingNode))
                {
                    mappingNode = new AeEventTypeMappingState(node.EventType.EventTypeMapping, namespaceIndex);
                    EventTypeNodes.Add(mappingNode.NodeId, mappingNode);

                    // ensure the mapping node is in the type table.
                    if (typeTable != null)
                    {
                        if (!typeTable.IsKnown(mappingNode.NodeId))
                        {
                            typeTable.AddSubtype(mappingNode.NodeId, mappingNode.SuperTypeId);
                        }
                    }
                }

                EventTypeNodes.Add(node.NodeId, node);

                // ensure the type node is in the type table.
                if (typeTable != null)
                {
                    if (!typeTable.IsKnown(node.NodeId))
                    {
                        typeTable.AddSubtype(node.NodeId, mappingNode.NodeId);
                    }
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Returns the type identified by the category id and condition name.
        /// </summary>
        public AeEventTypeState FindType(ServerSystemContext context, NodeId nodeId)
        {
            if (NodeId.IsNull(nodeId))
            {
                return(null);
            }

            BaseObjectTypeState eventType = null;

            if (!EventTypeNodes.TryGetValue(nodeId, out eventType))
            {
                return(null);
            }

            return(eventType as AeEventTypeState);
        }
コード例 #4
0
        /// <summary>
        /// Converts a ReferenceDescription to an IReference.
        /// </summary>
        private IReference ToReference(ReferenceDescription reference)
        {
            if (reference.NodeId.IsAbsolute || reference.TypeDefinition.IsAbsolute)
            {
                return(new NodeStateReference(reference.ReferenceTypeId, !reference.IsForward, reference.NodeId));
            }

            if (m_source != null && (reference.NodeId == ObjectIds.ObjectsFolder || reference.NodeId == ObjectIds.Server))
            {
                return(new NodeStateReference(reference.ReferenceTypeId, !reference.IsForward, m_rootId));
            }

            NodeState target = null;

            switch (reference.NodeClass)
            {
            case NodeClass.DataType: { target = new DataTypeState(); break; }

            case NodeClass.Method: { target = new MethodState(null); break; }

            case NodeClass.Object: { target = new BaseObjectState(null); break; }

            case NodeClass.ObjectType: { target = new BaseObjectTypeState(); break; }

            case NodeClass.ReferenceType: { target = new ReferenceTypeState(); break; }

            case NodeClass.Variable: { target = new BaseDataVariableState(null); break; }

            case NodeClass.VariableType: { target = new BaseDataVariableTypeState(); break; }

            case NodeClass.View: { target = new ViewState(); break; }
            }

            target.NodeId      = m_mapper.ToLocalId((NodeId)reference.NodeId);
            target.BrowseName  = m_mapper.ToLocalName(reference.BrowseName);
            target.DisplayName = reference.DisplayName;

            if (target is BaseInstanceState)
            {
                ((BaseInstanceState)target).TypeDefinitionId = m_mapper.ToLocalId((NodeId)reference.TypeDefinition);
            }

            return(new NodeStateReference(reference.ReferenceTypeId, !reference.IsForward, target));
        }
コード例 #5
0
        /// <summary>
        /// Helper to create an ObjectType-Node. Note: __NO__ NodeId is created by the default!
        /// Must be done by outer functionality!!
        /// </summary>
        /// <param name="browseDisplayName">Name displayed in the node tree</param>
        /// <param name="superTypeId">Base class or similar</param>
        /// <param name="presetNodeId">Preset the NodeId</param>
        /// <param name="descriptionKey">Lookup a Description on AAS literal/ refSemantics</param>
        /// <param name="modellingRule">Modeling Rule, if not None</param>
        /// <returns>THe node</returns>
        public static BaseObjectTypeState CreateObjectType(
            string browseDisplayName,
            NodeId superTypeId,
            NodeId presetNodeId         = null,
            string descriptionKey       = null,
            ModellingRule modellingRule = ModellingRule.None)
        {
            var x = new BaseObjectTypeState();

            x.BrowseName  = "" + browseDisplayName;
            x.DisplayName = "" + browseDisplayName;
            x.Description = new LocalizedText("en", browseDisplayName);
            x.Description = SetLocalizedTextWithDescription(x.Description, descriptionKey);
            x.SuperTypeId = superTypeId;
            if (presetNodeId != null)
            {
                x.NodeId = presetNodeId;
            }
            CheckSetModellingRule(modellingRule, x);
            return(x);
        }
コード例 #6
0
        /// <summary>
        /// Returns the node for the event type mapping identified by the node id.
        /// </summary>
        public AeEventTypeMappingState GetMappingNode(ServerSystemContext context, NodeId nodeId)
        {
            BaseObjectTypeState objectType = null;

            if (!EventTypeNodes.TryGetValue(nodeId, out objectType))
            {
                return(null);
            }

            AeEventTypeMappingState mappingNode = objectType as AeEventTypeMappingState;

            if (mappingNode == null)
            {
                return(null);
            }

            if (context.TypeTable.FindSubTypes(mappingNode.NodeId).Count == 0)
            {
                return(null);
            }

            return(mappingNode);
        }
コード例 #7
0
        /// <summary>
        /// Imports a node from the set.
        /// </summary>
        private NodeState Import(ISystemContext context, UANode node)
        {
            NodeState importedNode = null;

            NodeClass nodeClass = NodeClass.Unspecified;

            if (node is UAObject)
            {
                nodeClass = NodeClass.Object;
            }
            else if (node is UAVariable)
            {
                nodeClass = NodeClass.Variable;
            }
            else if (node is UAMethod)
            {
                nodeClass = NodeClass.Method;
            }
            else if (node is UAObjectType)
            {
                nodeClass = NodeClass.ObjectType;
            }
            else if (node is UAVariableType)
            {
                nodeClass = NodeClass.VariableType;
            }
            else if (node is UADataType)
            {
                nodeClass = NodeClass.DataType;
            }
            else if (node is UAReferenceType)
            {
                nodeClass = NodeClass.ReferenceType;
            }
            else if (node is UAView)
            {
                nodeClass = NodeClass.View;
            }

            switch (nodeClass)
            {
            case NodeClass.Object:
            {
                UAObject        o     = (UAObject)node;
                BaseObjectState value = new BaseObjectState(null);
                value.EventNotifier = o.EventNotifier;
                importedNode        = value;
                break;
            }

            case NodeClass.Variable:
            {
                UAVariable o = (UAVariable)node;

                NodeId typeDefinitionId = null;

                if (node.References != null)
                {
                    for (int ii = 0; ii < node.References.Length; ii++)
                    {
                        Opc.Ua.NodeId         referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true);
                        bool                  isInverse       = !node.References[ii].IsForward;
                        Opc.Ua.ExpandedNodeId targetId        = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris);

                        if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse)
                        {
                            typeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris);
                            break;
                        }
                    }
                }

                BaseVariableState value = null;

                if (typeDefinitionId == Opc.Ua.VariableTypeIds.PropertyType)
                {
                    value = new PropertyState(null);
                }
                else
                {
                    value = new BaseDataVariableState(null);
                }

                value.DataType                = ImportNodeId(o.DataType, context.NamespaceUris, true);
                value.ValueRank               = o.ValueRank;
                value.ArrayDimensions         = ImportArrayDimensions(o.ArrayDimensions);
                value.AccessLevelEx           = o.AccessLevel;
                value.UserAccessLevel         = (byte)(o.AccessLevel & 0xFF);
                value.MinimumSamplingInterval = o.MinimumSamplingInterval;
                value.Historizing             = o.Historizing;

                if (o.Value != null)
                {
                    XmlDecoder decoder  = CreateDecoder(context, o.Value);
                    TypeInfo   typeInfo = null;
                    value.Value = decoder.ReadVariantContents(out typeInfo);
                    decoder.Close();
                }

                importedNode = value;
                break;
            }

            case NodeClass.Method:
            {
                UAMethod    o     = (UAMethod)node;
                MethodState value = new MethodState(null);
                value.Executable       = o.Executable;
                value.UserExecutable   = o.Executable;
                value.TypeDefinitionId = ImportNodeId(o.MethodDeclarationId, context.NamespaceUris, true);
                importedNode           = value;
                break;
            }

            case NodeClass.View:
            {
                UAView    o     = (UAView)node;
                ViewState value = new ViewState();
                value.ContainsNoLoops = o.ContainsNoLoops;
                importedNode          = value;
                break;
            }

            case NodeClass.ObjectType:
            {
                UAObjectType        o     = (UAObjectType)node;
                BaseObjectTypeState value = new BaseObjectTypeState();
                value.IsAbstract = o.IsAbstract;
                importedNode     = value;
                break;
            }

            case NodeClass.VariableType:
            {
                UAVariableType        o     = (UAVariableType)node;
                BaseVariableTypeState value = new BaseDataVariableTypeState();
                value.IsAbstract      = o.IsAbstract;
                value.DataType        = ImportNodeId(o.DataType, context.NamespaceUris, true);
                value.ValueRank       = o.ValueRank;
                value.ArrayDimensions = ImportArrayDimensions(o.ArrayDimensions);

                if (o.Value != null)
                {
                    XmlDecoder decoder  = CreateDecoder(context, o.Value);
                    TypeInfo   typeInfo = null;
                    value.Value = decoder.ReadVariantContents(out typeInfo);
                    decoder.Close();
                }

                importedNode = value;
                break;
            }

            case NodeClass.DataType:
            {
                UADataType    o     = (UADataType)node;
                DataTypeState value = new DataTypeState();
                value.IsAbstract = o.IsAbstract;
                Opc.Ua.DataTypeDefinition dataTypeDefinition = Import(o, o.Definition, context.NamespaceUris);
                value.DataTypeDefinition = new ExtensionObject(dataTypeDefinition);
                value.Purpose            = o.Purpose;
                value.DataTypeModifier   = DataTypeModifier.None;

                if (o.Definition != null)
                {
                    if (o.Definition.IsOptionSet)
                    {
                        value.DataTypeModifier = DataTypeModifier.OptionSet;
                    }
                    else if (o.Definition.IsUnion)
                    {
                        value.DataTypeModifier = DataTypeModifier.Union;
                    }
                }

                importedNode = value;
                break;
            }

            case NodeClass.ReferenceType:
            {
                UAReferenceType    o     = (UAReferenceType)node;
                ReferenceTypeState value = new ReferenceTypeState();
                value.IsAbstract  = o.IsAbstract;
                value.InverseName = Import(o.InverseName);
                value.Symmetric   = o.Symmetric;
                importedNode      = value;
                break;
            }
            }

            importedNode.NodeId      = ImportNodeId(node.NodeId, context.NamespaceUris, false);
            importedNode.BrowseName  = ImportQualifiedName(node.BrowseName, context.NamespaceUris);
            importedNode.DisplayName = Import(node.DisplayName);

            if (importedNode.DisplayName == null)
            {
                importedNode.DisplayName = new Ua.LocalizedText(importedNode.BrowseName.Name);
            }

            importedNode.Description   = Import(node.Description);
            importedNode.Categories    = (node.Category != null && node.Category.Length > 0) ? node.Category : null;
            importedNode.ReleaseStatus = node.ReleaseStatus;
            importedNode.WriteMask     = (AttributeWriteMask)node.WriteMask;
            importedNode.UserWriteMask = (AttributeWriteMask)node.UserWriteMask;
            importedNode.Extensions    = node.Extensions;

            if (!String.IsNullOrEmpty(node.SymbolicName))
            {
                importedNode.SymbolicName = node.SymbolicName;
            }

            if (node.References != null)
            {
                BaseInstanceState instance = importedNode as BaseInstanceState;
                BaseTypeState     type     = importedNode as BaseTypeState;

                for (int ii = 0; ii < node.References.Length; ii++)
                {
                    Opc.Ua.NodeId         referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true);
                    bool                  isInverse       = !node.References[ii].IsForward;
                    Opc.Ua.ExpandedNodeId targetId        = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris);

                    if (instance != null)
                    {
                        if (referenceTypeId == ReferenceTypeIds.HasModellingRule && !isInverse)
                        {
                            instance.ModellingRuleId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris);
                            continue;
                        }

                        if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse)
                        {
                            instance.TypeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris);
                            continue;
                        }
                    }

                    if (type != null)
                    {
                        if (referenceTypeId == ReferenceTypeIds.HasSubtype && isInverse)
                        {
                            type.SuperTypeId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris);
                            continue;
                        }
                    }

                    importedNode.AddReference(referenceTypeId, isInverse, targetId);
                }
            }

            return(importedNode);
        }
コード例 #8
0
        /// <summary>
        /// Adds a node to the set.
        /// </summary>
        public void Export(ISystemContext context, NodeState node, bool outputRedundantNames = true)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            if (Opc.Ua.NodeId.IsNull(node.NodeId))
            {
                throw new ArgumentException("A non-null NodeId must be specified.");
            }

            UANode exportedNode = null;

            switch (node.NodeClass)
            {
            case NodeClass.Object:
            {
                BaseObjectState o     = (BaseObjectState)node;
                UAObject        value = new UAObject();
                value.EventNotifier = o.EventNotifier;

                if (o.Parent != null)
                {
                    value.ParentNodeId = ExportAlias(o.Parent.NodeId, context.NamespaceUris);
                }

                exportedNode = value;
                break;
            }

            case NodeClass.Variable:
            {
                BaseVariableState o     = (BaseVariableState)node;
                UAVariable        value = new UAVariable();
                value.DataType                = ExportAlias(o.DataType, context.NamespaceUris);
                value.ValueRank               = o.ValueRank;
                value.ArrayDimensions         = Export(o.ArrayDimensions);
                value.AccessLevel             = o.AccessLevelEx;
                value.MinimumSamplingInterval = o.MinimumSamplingInterval;
                value.Historizing             = o.Historizing;

                if (o.Parent != null)
                {
                    value.ParentNodeId = ExportAlias(o.Parent.NodeId, context.NamespaceUris);
                }

                if (o.Value != null)
                {
                    XmlEncoder encoder = CreateEncoder(context);

                    Variant variant = new Variant(o.Value);
                    encoder.WriteVariantContents(variant.Value, variant.TypeInfo);

                    XmlDocument document = new XmlDocument();
                    document.InnerXml = encoder.Close();
                    value.Value       = document.DocumentElement;
                }

                exportedNode = value;
                break;
            }

            case NodeClass.Method:
            {
                MethodState o     = (MethodState)node;
                UAMethod    value = new UAMethod();
                value.Executable = o.Executable;

                if (o.TypeDefinitionId != null && !o.TypeDefinitionId.IsNullNodeId && o.TypeDefinitionId != o.NodeId)
                {
                    value.MethodDeclarationId = Export(o.TypeDefinitionId, context.NamespaceUris);
                }

                if (o.Parent != null)
                {
                    value.ParentNodeId = ExportAlias(o.Parent.NodeId, context.NamespaceUris);
                }

                exportedNode = value;
                break;
            }

            case NodeClass.View:
            {
                ViewState o     = (ViewState)node;
                UAView    value = new UAView();
                value.ContainsNoLoops = o.ContainsNoLoops;
                exportedNode          = value;
                break;
            }

            case NodeClass.ObjectType:
            {
                BaseObjectTypeState o     = (BaseObjectTypeState)node;
                UAObjectType        value = new UAObjectType();
                value.IsAbstract = o.IsAbstract;
                exportedNode     = value;
                break;
            }

            case NodeClass.VariableType:
            {
                BaseVariableTypeState o     = (BaseVariableTypeState)node;
                UAVariableType        value = new UAVariableType();
                value.IsAbstract      = o.IsAbstract;
                value.DataType        = ExportAlias(o.DataType, context.NamespaceUris);
                value.ValueRank       = o.ValueRank;
                value.ArrayDimensions = Export(o.ArrayDimensions);

                if (o.Value != null)
                {
                    XmlEncoder encoder = CreateEncoder(context);

                    Variant variant = new Variant(o.Value);
                    encoder.WriteVariantContents(variant.Value, variant.TypeInfo);

                    XmlDocument document = new XmlDocument();
                    document.InnerXml = encoder.Close();
                    value.Value       = document.DocumentElement;
                }

                exportedNode = value;
                break;
            }

            case NodeClass.DataType:
            {
                DataTypeState o     = (DataTypeState)node;
                UADataType    value = new UADataType();
                value.IsAbstract = o.IsAbstract;
                value.Definition = Export(o, o.DataTypeDefinition, context.NamespaceUris, outputRedundantNames);
                value.Purpose    = o.Purpose;
                exportedNode     = value;
                break;
            }

            case NodeClass.ReferenceType:
            {
                ReferenceTypeState o     = (ReferenceTypeState)node;
                UAReferenceType    value = new UAReferenceType();
                value.IsAbstract = o.IsAbstract;

                if (!Opc.Ua.LocalizedText.IsNullOrEmpty(o.InverseName))
                {
                    value.InverseName = Export(new Opc.Ua.LocalizedText[] { o.InverseName });
                }

                value.Symmetric = o.Symmetric;
                exportedNode    = value;
                break;
            }
            }

            exportedNode.NodeId     = Export(node.NodeId, context.NamespaceUris);
            exportedNode.BrowseName = Export(node.BrowseName, context.NamespaceUris);

            if (outputRedundantNames || node.DisplayName.Text != node.BrowseName.Name)
            {
                exportedNode.DisplayName = Export(new Opc.Ua.LocalizedText[] { node.DisplayName });
            }
            else
            {
                exportedNode.DisplayName = null;
            }

            if (node.Description != null && !String.IsNullOrEmpty(node.Description.Text))
            {
                exportedNode.Description = Export(new Opc.Ua.LocalizedText[] { node.Description });
            }
            else
            {
                exportedNode.Description = new LocalizedText[0];
            }

            exportedNode.Category      = (node.Categories != null && node.Categories.Count > 0) ? new List <string>(node.Categories).ToArray() : null;
            exportedNode.ReleaseStatus = node.ReleaseStatus;
            exportedNode.WriteMask     = (uint)node.WriteMask;
            exportedNode.UserWriteMask = (uint)node.UserWriteMask;
            exportedNode.Extensions    = node.Extensions;

            if (!String.IsNullOrEmpty(node.SymbolicName) && node.SymbolicName != node.BrowseName.Name)
            {
                exportedNode.SymbolicName = node.SymbolicName;
            }

            // export references.
            INodeBrowser     browser            = node.CreateBrowser(context, null, null, true, BrowseDirection.Both, null, null, true);
            List <Reference> exportedReferences = new List <Reference>();
            IReference       reference          = browser.Next();

            while (reference != null)
            {
                if (node.NodeClass == NodeClass.Method)
                {
                    if (!reference.IsInverse && reference.ReferenceTypeId == ReferenceTypeIds.HasTypeDefinition)
                    {
                        reference = browser.Next();
                        continue;
                    }
                }

                Reference exportedReference = new Reference();

                exportedReference.ReferenceType = ExportAlias(reference.ReferenceTypeId, context.NamespaceUris);
                exportedReference.IsForward     = !reference.IsInverse;
                exportedReference.Value         = Export(reference.TargetId, context.NamespaceUris, context.ServerUris);
                exportedReferences.Add(exportedReference);

                reference = browser.Next();
            }

            exportedNode.References = exportedReferences.ToArray();

            // add node to list.
            UANode[] nodes = null;

            int count = 1;

            if (this.Items == null)
            {
                nodes = new UANode[count];
            }
            else
            {
                count += this.Items.Length;
                nodes  = new UANode[count];
                Array.Copy(this.Items, nodes, this.Items.Length);
            }

            nodes[count - 1] = exportedNode;

            this.Items = nodes;

            // recusively process children.
            List <BaseInstanceState> children = new List <BaseInstanceState>();

            node.GetChildren(context, children);

            for (int ii = 0; ii < children.Count; ii++)
            {
                Export(context, children[ii], outputRedundantNames);
            }
        }
コード例 #9
0
        /// <summary>
        /// Convert to stack object
        /// </summary>
        /// <param name="nodeModel"></param>
        /// <param name="context"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        public static NodeState ToNodeState(this BaseNodeModel nodeModel, ISystemContext context,
                                            NodeState parent = null)
        {
            NodeState state;

            switch (nodeModel)
            {
            case ViewNodeModel viewState:
                state = new ViewState {
                    ContainsNoLoops = viewState.ContainsNoLoops ?? false,
                    EventNotifier   = viewState.EventNotifier ?? EventNotifiers.None,
                };
                break;

            case TypeNodeModel typeState:
                switch (typeState)
                {
                case VariableTypeNodeModel variableType:
                    switch (variableType)
                    {
                    case DataVariableTypeNodeModel data:
                        state = new BaseDataVariableTypeState();
                        break;

                    case PropertyTypeNodeModel property:
                        state = new PropertyTypeState();
                        break;

                    default:
                        return(null);
                    }
                    var baseVariableTypeState = state as BaseVariableTypeState;
                    baseVariableTypeState.ArrayDimensions =
                        variableType.ArrayDimensions;
                    baseVariableTypeState.DataType =
                        variableType.DataType;
                    baseVariableTypeState.ValueRank =
                        variableType.ValueRank ?? ValueRanks.Scalar;
                    baseVariableTypeState.WrappedValue =
                        variableType.Value ?? Variant.Null;
                    break;

                case ObjectTypeNodeModel objectType:
                    state = new BaseObjectTypeState();
                    break;

                case ReferenceTypeNodeModel referenceType:
                    state = new ReferenceTypeState {
                        Symmetric   = referenceType.Symmetric ?? false,
                        InverseName = referenceType.InverseName
                    };
                    break;

                case DataTypeNodeModel dataType:
                    state = new DataTypeState {
                        //  Definition = dataType.Definition.ToDataTypeDefinition()
                    };
                    break;

                default:
                    return(null);
                }
                var baseTypeState = state as BaseTypeState;
                baseTypeState.IsAbstract = typeState.IsAbstract ?? false;
                break;

            case InstanceNodeModel instanceState:
                switch (instanceState)
                {
                case VariableNodeModel variable:
                    switch (variable)
                    {
                    case DataVariableNodeModel data:
                        state = new BaseDataVariableState(parent);
                        break;

                    case PropertyNodeModel property:
                        state = new PropertyState(parent);
                        break;

                    default:
                        return(null);
                    }
                    var baseVariableState = state as BaseVariableState;
                    baseVariableState.ArrayDimensions =
                        variable.ArrayDimensions;
                    baseVariableState.DataType =
                        variable.DataType;
                    baseVariableState.ValueRank =
                        variable.ValueRank ?? ValueRanks.Scalar;
                    baseVariableState.Value =
                        variable.Value?.Value;
                    baseVariableState.AccessLevel =
                        variable.AccessLevel ?? AccessLevels.CurrentRead;
                    baseVariableState.UserAccessLevel =
                        variable.UserAccessLevel ?? AccessLevels.CurrentRead;
                    baseVariableState.IsValueType =
                        variable.IsValueType;
                    baseVariableState.Historizing =
                        variable.Historizing ?? false;
                    baseVariableState.MinimumSamplingInterval =
                        variable.MinimumSamplingInterval ?? 0.0;
                    baseVariableState.ModellingRuleId =
                        variable.ModellingRuleId;
                    baseVariableState.NumericId =
                        variable.NumericId;
                    baseVariableState.ReferenceTypeId =
                        variable.ReferenceTypeId;
                    baseVariableState.StatusCode =
                        variable.StatusCode ?? StatusCodes.Good;
                    baseVariableState.Timestamp =
                        variable.Timestamp ?? DateTime.MinValue;
                    baseVariableState.TypeDefinitionId =
                        variable.TypeDefinitionId;
                    break;

                case ObjectNodeModel obj:
                    state = new BaseObjectState(parent)
                    {
                        EventNotifier = obj.EventNotifier ?? EventNotifiers.None
                    };
                    break;

                case MethodNodeModel method:
                    state = new MethodState(parent)
                    {
                        UserExecutable      = method.UserExecutable,
                        Executable          = method.Executable,
                        MethodDeclarationId = method.MethodDeclarationId
                    };
                    break;

                default:
                    return(null);
                }
                break;

            default:
                return(null);
            }
            state.BrowseName    = nodeModel.BrowseName;
            state.Description   = nodeModel.Description;
            state.DisplayName   = nodeModel.DisplayName;
            state.Handle        = nodeModel.Handle;
            state.NodeId        = nodeModel.NodeId;
            state.SymbolicName  = nodeModel.SymbolicName;
            state.WriteMask     = nodeModel.WriteMask ?? AttributeWriteMask.None;
            state.UserWriteMask = nodeModel.UserWriteMask ?? AttributeWriteMask.None;
            state.Initialized   = true;
            foreach (var child in nodeModel.GetChildren(context))
            {
                state.AddChild(child.ToNodeState(context, state) as BaseInstanceState);
            }
            foreach (var reference in nodeModel.References)
            {
                state.AddReference(reference.ReferenceTypeId, reference.IsInverse,
                                   reference.TargetId);
            }
            return(state);
        }
コード例 #10
0
        /// <summary>
        /// Verifies that the specified node exists.
        /// </summary>
        protected override NodeState ValidateNode(
            ServerSystemContext context,
            NodeHandle handle,
            IDictionary <NodeId, NodeState> cache)
        {
            // not valid if no root.
            if (handle == null)
            {
                return(null);
            }

            // check if previously validated.
            if (handle.Validated)
            {
                return(handle.Node);
            }

            NodeState target = null;

            // check if already in the cache.
            if (cache != null)
            {
                if (cache.TryGetValue(handle.NodeId, out target))
                {
                    // nulls mean a NodeId which was previously found to be invalid has been referenced again.
                    if (target == null)
                    {
                        return(null);
                    }

                    handle.Node      = target;
                    handle.Validated = true;
                    return(handle.Node);
                }

                target = null;
            }

            try
            {
                // check if the node id has been parsed.
                AeParsedNodeId parsedNodeId = handle.ParsedNodeId as AeParsedNodeId;

                if (parsedNodeId == null)
                {
                    return(null);
                }

                ComAeClient client = m_system.SelectClient(context, false);

                switch (parsedNodeId.RootType)
                {
                case AeModelUtils.AeSimpleEventType:
                case AeModelUtils.AeTrackingEventType:
                case AeModelUtils.AeConditionEventType:
                {
                    if (m_typeCache == null)
                    {
                        return(null);
                    }

                    BaseObjectTypeState eventTypeNode = null;
                    NodeId rootId = AeParsedNodeId.Construct(parsedNodeId.RootType, parsedNodeId.CategoryId, parsedNodeId.ConditionName, parsedNodeId.NamespaceIndex);

                    if (!m_typeCache.EventTypeNodes.TryGetValue(rootId, out eventTypeNode))
                    {
                        return(null);
                    }

                    target = eventTypeNode;
                    break;
                }

                case AeModelUtils.AeArea:
                {
                    ComAeBrowserClient browser = new ComAeBrowserClient(client, null);
                    target = browser.FindArea(context, parsedNodeId.RootId, NamespaceIndex);
                    browser.Dispose();

                    handle.Validated = true;
                    handle.Node      = target;
                    return(handle.Node);
                }

                case AeModelUtils.AeSource:
                {
                    ComAeBrowserClient browser = new ComAeBrowserClient(client, null);
                    target = browser.FindSource(context, parsedNodeId.RootId, parsedNodeId.ComponentPath, NamespaceIndex);
                    browser.Dispose();

                    handle.Validated = true;
                    handle.Node      = target;
                    return(handle.Node);
                }

                case AeModelUtils.AeCondition:
                {
                    target = new AeConditionState(context, handle, m_templateAlarm.Acknowledge);
                    break;
                }
                }

                // node does not exist.
                if (target == null)
                {
                    return(null);
                }

                if (!String.IsNullOrEmpty(parsedNodeId.ComponentPath))
                {
                    // validate component.
                    NodeState component = target.FindChildBySymbolicName(context, parsedNodeId.ComponentPath);

                    // component does not exist.
                    if (component == null)
                    {
                        return(null);
                    }

                    target = component;
                }

                // found a valid component.
                handle.Validated = true;
                handle.Node      = target;
                return(handle.Node);
            }
            finally
            {
                // store the node in the cache to optimize subsequent lookups.
                if (cache != null)
                {
                    cache.Add(handle.NodeId, target);
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// Imports a node from the set.
        /// </summary>
        private NodeState Import(ISystemContext context, UANode node)
        {
            NodeState importedNode = null;

            NodeClass nodeClass = NodeClass.Unspecified;

            if (node is UAObject) nodeClass = NodeClass.Object;
            else if (node is UAVariable) nodeClass = NodeClass.Variable;
            else if (node is UAMethod) nodeClass = NodeClass.Method;
            else if (node is UAObjectType) nodeClass = NodeClass.ObjectType;
            else if (node is UAVariableType) nodeClass = NodeClass.VariableType;
            else if (node is UADataType) nodeClass = NodeClass.DataType;
            else if (node is UAReferenceType) nodeClass = NodeClass.ReferenceType;
            else if (node is UAView) nodeClass = NodeClass.View;

            switch (nodeClass)
            {
                case NodeClass.Object:
                {
                    UAObject o = (UAObject)node;
                    BaseObjectState value = new BaseObjectState(null);
                    value.EventNotifier = o.EventNotifier;
                    importedNode = value;
                    break;
                }

                case NodeClass.Variable:
                {
                    UAVariable o = (UAVariable)node;

                    NodeId typeDefinitionId = null;

                    if (node.References != null)
                    {
                        for (int ii = 0; ii < node.References.Length; ii++)
                        {
                            Opc.Ua.NodeId referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true);
                            bool isInverse = !node.References[ii].IsForward;
                            Opc.Ua.ExpandedNodeId targetId = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris);

                            if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse)
                            {
                                typeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris);
                                break;
                            }
                        }
                    }

                    BaseVariableState value = null;

                    if (typeDefinitionId == Opc.Ua.VariableTypeIds.PropertyType)
                    {
                        value = new PropertyState(null);
                    }
                    else
                    {
                        value = new BaseDataVariableState(null);
                    }

                    value.DataType = ImportNodeId(o.DataType, context.NamespaceUris, true);
                    value.ValueRank = o.ValueRank;
                    value.ArrayDimensions = ImportArrayDimensions(o.ArrayDimensions);
                    value.AccessLevel = o.AccessLevel;
                    value.UserAccessLevel = o.UserAccessLevel;
                    value.MinimumSamplingInterval = o.MinimumSamplingInterval;
                    value.Historizing = o.Historizing;

                    if (o.Value != null)
                    {
                        XmlDecoder decoder = CreateDecoder(context, o.Value);
                        TypeInfo typeInfo = null;
                        value.Value = decoder.ReadVariantContents(out typeInfo);
                        decoder.Close();
                    }

                    importedNode = value;
                    break;
                }

                case NodeClass.Method:
                {
                    UAMethod o = (UAMethod)node;
                    MethodState value = new MethodState(null);
                    value.Executable = o.Executable;
                    value.UserExecutable = o.UserExecutable;
                    importedNode = value;
                    break;
                }

                case NodeClass.View:
                {
                    UAView o = (UAView)node;
                    ViewState value = new ViewState();
                    value.ContainsNoLoops = o.ContainsNoLoops;
                    importedNode = value;
                    break;
                }

                case NodeClass.ObjectType:
                {
                    UAObjectType o = (UAObjectType)node;
                    BaseObjectTypeState value = new BaseObjectTypeState();
                    value.IsAbstract = o.IsAbstract;
                    importedNode = value;
                    break;
                }

                case NodeClass.VariableType:
                {
                    UAVariableType o = (UAVariableType)node;
                    BaseVariableTypeState value = new BaseDataVariableTypeState();
                    value.IsAbstract = o.IsAbstract;
                    value.DataType = ImportNodeId(o.DataType, context.NamespaceUris, true);
                    value.ValueRank = o.ValueRank;
                    value.ArrayDimensions = ImportArrayDimensions(o.ArrayDimensions);

                    if (o.Value != null)
                    {
                        XmlDecoder decoder = CreateDecoder(context, o.Value);
                        TypeInfo typeInfo = null;
                        value.Value = decoder.ReadVariantContents(out typeInfo);
                        decoder.Close();
                    }

                    importedNode = value;
                    break;
                }

                case NodeClass.DataType:
                {
                    UADataType o = (UADataType)node;
                    DataTypeState value = new DataTypeState();
                    value.IsAbstract = o.IsAbstract;
                    value.Definition = Import(o.Definition, context.NamespaceUris);
                    importedNode = value;
                    break;
                }

                case NodeClass.ReferenceType:
                {
                    UAReferenceType o = (UAReferenceType)node;
                    ReferenceTypeState value = new ReferenceTypeState();
                    value.IsAbstract = o.IsAbstract;
                    value.InverseName = Import(o.InverseName);
                    value.Symmetric = o.Symmetric;
                    importedNode = value;
                    break;
                }
            }

            importedNode.NodeId = ImportNodeId(node.NodeId, context.NamespaceUris, false);
            importedNode.BrowseName = ImportQualifiedName(node.BrowseName, context.NamespaceUris);
            importedNode.DisplayName = Import(node.DisplayName);
            importedNode.Description = Import(node.Description);
            importedNode.WriteMask = (AttributeWriteMask)node.WriteMask;
            importedNode.UserWriteMask = (AttributeWriteMask)node.UserWriteMask;

            if (!String.IsNullOrEmpty(node.SymbolicName))
            {
                importedNode.SymbolicName = node.SymbolicName;
            }

            if (node.References != null)
            {
                BaseInstanceState instance = importedNode as BaseInstanceState;
                BaseTypeState type = importedNode as BaseTypeState;

                for (int ii = 0; ii < node.References.Length; ii++)
                {
                    Opc.Ua.NodeId referenceTypeId = ImportNodeId(node.References[ii].ReferenceType, context.NamespaceUris, true);
                    bool isInverse = !node.References[ii].IsForward;
                    Opc.Ua.ExpandedNodeId targetId = ImportExpandedNodeId(node.References[ii].Value, context.NamespaceUris, context.ServerUris);

                    if (instance != null)
                    {
                        if (referenceTypeId == ReferenceTypeIds.HasModellingRule && !isInverse)
                        {
                            instance.ModellingRuleId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris);
                            continue;
                        }

                        if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse)
                        {
                            instance.TypeDefinitionId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris);
                            continue;
                        }
                    }

                    if (type != null)
                    {
                        if (referenceTypeId == ReferenceTypeIds.HasSubtype && isInverse)
                        {
                            type.SuperTypeId = Opc.Ua.ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris);
                            continue;
                        }
                    }

                    importedNode.AddReference(referenceTypeId, isInverse, targetId);
                }
            }

            return importedNode;
        }
コード例 #12
0
        /// <summary>
        /// Does any initialization required before the address space can be used.
        /// </summary>
        /// <remarks>
        /// The externalReferences is an out parameter that allows the node manager to link to nodes
        /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and
        /// should have a reference to the root folder node(s) exposed by this node manager.
        /// </remarks>
        public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences)
        {
            lock (Lock)
            {
                //counter for the NodeId identifier:
                uint id = 1;

                // Define the nodes:

                #region sample nodes
                //----------------- A few examples of hard coded nodes in the Address Space -------------------
                //a first node:
                BaseObjectState testObjectNode = new BaseObjectState(null);
                // Set the attributes:
                testObjectNode.NodeId           = new NodeId(id++, NamespaceIndex);
                testObjectNode.BrowseName       = new QualifiedName("test_ObjectNode", NamespaceIndex);
                testObjectNode.DisplayName      = testObjectNode.BrowseName.Name;
                testObjectNode.TypeDefinitionId = ObjectTypeIds.BaseObjectType;

                // ensure testObjectNode can be found via the server object: add references to/from it!
                IList <IReference> references = null;

                if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references))
                {
                    externalReferences[ObjectIds.ObjectsFolder] = references = new List <IReference>();
                }

                testObjectNode.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder);
                references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, testObjectNode.NodeId));

                //a second node:
                PropertyState testPropertyNode = new PropertyState(testObjectNode);
                // Set the attributes:
                testPropertyNode.NodeId           = new NodeId(id++, NamespaceIndex);
                testPropertyNode.BrowseName       = new QualifiedName("test_PropertyNode", NamespaceIndex);
                testPropertyNode.DisplayName      = testPropertyNode.BrowseName.Name;
                testPropertyNode.TypeDefinitionId = VariableTypeIds.PropertyType;
                testPropertyNode.ReferenceTypeId  = ReferenceTypeIds.HasProperty;
                testPropertyNode.DataType         = DataTypeIds.Int32;
                testPropertyNode.ValueRank        = ValueRanks.OneDimension;
                testPropertyNode.ArrayDimensions  = new ReadOnlyList <uint>(new uint[] { 5 });
                testPropertyNode.Value            = new int[] { 7, -18, 56, 0, 3 };
                //add this node as a child of the previous node:
                testObjectNode.AddChild(testPropertyNode);
                // save in dictionary.
                AddPredefinedNode(SystemContext, testObjectNode);
                //---------------------------------------------------------------------------------------------
                #endregion

                #region tetris simulation nodes
                //------------------------------ The nodes for the tetris simulation --------------------------

                // The object node under wich the other nodes containing the data will be organized:
                BaseObjectState tetrisSimulationNode = new BaseObjectState(null);
                tetrisSimulationNode.NodeId           = new NodeId(id++, NamespaceIndex);
                tetrisSimulationNode.BrowseName       = new QualifiedName("Tetris_Simulation", NamespaceIndex);
                tetrisSimulationNode.DisplayName      = tetrisSimulationNode.BrowseName.Name;
                tetrisSimulationNode.SymbolicName     = tetrisSimulationNode.BrowseName.Name;
                tetrisSimulationNode.TypeDefinitionId = ObjectTypeIds.BaseObjectType;

                // ensure tetrisSimulationNode can be found via the server object: add references to/from it!
                references = null;
                if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references))
                {
                    externalReferences[ObjectIds.ObjectsFolder] = references = new List <IReference>();
                }
                // Forward Reference FROM the ObjectsFolder node TO our tetris node:
                references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, tetrisSimulationNode.NodeId));

                // Inverse Reference FROM our tetris node TO the ObjectsFolder node:
                tetrisSimulationNode.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder);

                // -------------------- Nodes containing data -------------------
                // The nodes containing some simulated tetris data:

                //Score:
                BaseDataVariableState simulatedScoreNode = new BaseDataVariableState(tetrisSimulationNode);
                simulatedScoreNode.NodeId           = new NodeId(id++, NamespaceIndex);
                simulatedScoreNode.BrowseName       = new QualifiedName("simulated_Score", NamespaceIndex);
                simulatedScoreNode.DisplayName      = simulatedScoreNode.BrowseName.Name;
                simulatedScoreNode.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
                simulatedScoreNode.ReferenceTypeId  = ReferenceTypeIds.HasComponent;
                simulatedScoreNode.DataType         = DataTypeIds.Int32;
                simulatedScoreNode.ValueRank        = ValueRanks.Scalar;
                //add the reference from the Tetris_Simulation Object Node to this one:
                tetrisSimulationNode.AddChild(simulatedScoreNode);

                //Game Over status:
                BaseDataVariableState simulatedGameOverNode = new BaseDataVariableState(tetrisSimulationNode);
                simulatedGameOverNode.NodeId           = new NodeId(id++, NamespaceIndex);
                simulatedGameOverNode.BrowseName       = new QualifiedName("simulated_GameOver", NamespaceIndex);
                simulatedGameOverNode.DisplayName      = simulatedGameOverNode.BrowseName.Name;
                simulatedGameOverNode.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
                simulatedGameOverNode.ReferenceTypeId  = ReferenceTypeIds.HasComponent;
                simulatedGameOverNode.DataType         = DataTypeIds.Boolean;
                simulatedGameOverNode.ValueRank        = ValueRanks.Scalar;
                //add the reference from the Tetris_Simulation Object Node to this one:
                tetrisSimulationNode.AddChild(simulatedGameOverNode);

                //Paused status:
                BaseDataVariableState simulatedPausedNode = new BaseDataVariableState(tetrisSimulationNode);
                simulatedPausedNode.NodeId           = new NodeId(id++, NamespaceIndex);
                simulatedPausedNode.BrowseName       = new QualifiedName("simulated_Paused", NamespaceIndex);
                simulatedPausedNode.DisplayName      = simulatedPausedNode.BrowseName.Name;
                simulatedPausedNode.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
                simulatedPausedNode.ReferenceTypeId  = ReferenceTypeIds.HasComponent;
                simulatedPausedNode.DataType         = DataTypeIds.Boolean;
                simulatedPausedNode.ValueRank        = ValueRanks.Scalar;
                simulatedPausedNode.AccessLevel      = AccessLevels.CurrentReadOrWrite;
                simulatedPausedNode.Value            = false;
                //add the reference from the Tetris_Simulation Object Node to this one:
                tetrisSimulationNode.AddChild(simulatedPausedNode);
                //---------------------------------------------------------------

                AddPredefinedNode(SystemContext, tetrisSimulationNode);
                //---------------------------------------------------------------------------------------------
                #endregion

                #region teris game nodes
                //------------------------------ The nodes for the tetris game --------------------------------

                // The object node under wich the other nodes containing the data will be organized:
                BaseObjectState tetrisGameNode = new BaseObjectState(null);
                tetrisGameNode.NodeId           = new NodeId(id++, NamespaceIndex);
                tetrisGameNode.BrowseName       = new QualifiedName("Tetris_Game", NamespaceIndex);
                tetrisGameNode.DisplayName      = tetrisGameNode.BrowseName.Name;
                tetrisGameNode.SymbolicName     = tetrisGameNode.BrowseName.Name;
                tetrisGameNode.TypeDefinitionId = ObjectTypeIds.BaseObjectType;

                // ensure tetrisGameNode can be found via the server object: add references to/from it!
                references = null;
                if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references))
                {
                    externalReferences[ObjectIds.ObjectsFolder] = references = new List <IReference>();
                }
                // Forward Reference FROM the ObjectsFolder node TO our tetris node:
                references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, tetrisGameNode.NodeId));

                // Inverse Reference FROM our tetris node TO the ObjectsFolder node:
                tetrisGameNode.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder);

                //------------- Enable tetris node to report events ---------------
                //set the tetrisGameNode as EventNotifier:
                tetrisGameNode.EventNotifier = EventNotifiers.SubscribeToEvents;
                // Add a HasNotifier reference from Server object to our tetris node:
                Server.CoreNodeManager.AddReference(ObjectIds.Server, ReferenceTypeIds.HasNotifier, false, tetrisGameNode.NodeId, false);
                // Also do the inverse:
                // connect the tetrisGame node to the Server object by making it a Root Notifier (of our Node Manager)
                AddRootNotifier(tetrisGameNode); // an inverse reference from our tetris node to the Server object is added in here
                // (Note: A node added as a root notifier will report its events directly to the server object.
                //  This is not UA specific, but an SDK specific implementation.)
                //-----------------------------------------------------------------

                // -------------------- Nodes containing data -------------------
                // The nodes containing some simulated tetris data:

                //Score:
                BaseDataVariableState scoreNode = new BaseDataVariableState(tetrisGameNode);
                scoreNode.NodeId           = new NodeId(id++, NamespaceIndex);
                scoreNode.BrowseName       = new QualifiedName("Score", NamespaceIndex);
                scoreNode.DisplayName      = scoreNode.BrowseName.Name;
                scoreNode.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
                scoreNode.ReferenceTypeId  = ReferenceTypeIds.HasComponent;
                scoreNode.DataType         = DataTypeIds.Int32;
                scoreNode.ValueRank        = ValueRanks.Scalar;
                //add the reference from the Tetris_Game Object Node to this one:
                tetrisGameNode.AddChild(scoreNode);

                //Game Over status:
                BaseDataVariableState gameOverNode = new BaseDataVariableState(tetrisGameNode);
                gameOverNode.NodeId           = new NodeId(id++, NamespaceIndex);
                gameOverNode.BrowseName       = new QualifiedName("GameOver", NamespaceIndex);
                gameOverNode.DisplayName      = gameOverNode.BrowseName.Name;
                gameOverNode.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
                gameOverNode.ReferenceTypeId  = ReferenceTypeIds.HasComponent;
                gameOverNode.DataType         = DataTypeIds.Boolean;
                gameOverNode.ValueRank        = ValueRanks.Scalar;
                //add the reference from the Tetris_Game Object Node to this one:
                tetrisGameNode.AddChild(gameOverNode);

                //Paused status:
                BaseDataVariableState pausedNode = new BaseDataVariableState(tetrisGameNode);
                pausedNode.NodeId           = new NodeId(id++, NamespaceIndex);
                pausedNode.BrowseName       = new QualifiedName("Paused", NamespaceIndex);
                pausedNode.DisplayName      = pausedNode.BrowseName.Name;
                pausedNode.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
                pausedNode.ReferenceTypeId  = ReferenceTypeIds.HasComponent;
                pausedNode.DataType         = DataTypeIds.Boolean;
                pausedNode.ValueRank        = ValueRanks.Scalar;
                //add the reference from the Tetris_Game Object Node to this one:
                tetrisGameNode.AddChild(pausedNode);

                //SecondsTillUnpause:
                BaseDataVariableState secondsTillUnpauseNode = new BaseDataVariableState(tetrisGameNode);
                secondsTillUnpauseNode.NodeId           = new NodeId(id++, NamespaceIndex);
                secondsTillUnpauseNode.BrowseName       = new QualifiedName("Seconds_Till_Unpause", NamespaceIndex);
                secondsTillUnpauseNode.DisplayName      = secondsTillUnpauseNode.BrowseName.Name;
                secondsTillUnpauseNode.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
                secondsTillUnpauseNode.ReferenceTypeId  = ReferenceTypeIds.HasComponent;
                secondsTillUnpauseNode.DataType         = DataTypeIds.Int32;
                secondsTillUnpauseNode.ValueRank        = ValueRanks.Scalar;
                //add the reference from the Tetris_Game Object Node to this one:
                tetrisGameNode.AddChild(secondsTillUnpauseNode);

                //SecondsTillUnpause:
                BaseDataVariableState fieldNode = new BaseDataVariableState(tetrisGameNode);
                fieldNode.NodeId           = new NodeId(id++, NamespaceIndex);
                fieldNode.BrowseName       = new QualifiedName("Field", NamespaceIndex);
                fieldNode.DisplayName      = fieldNode.BrowseName.Name;
                fieldNode.TypeDefinitionId = VariableTypeIds.BaseDataVariableType;
                fieldNode.ReferenceTypeId  = ReferenceTypeIds.HasComponent;
                fieldNode.DataType         = DataTypeIds.Int32;
                fieldNode.ValueRank        = ValueRanks.TwoDimensions;
                //fieldNode.ArrayDimensions = ???
                // => get the matrix (twodimensional array) dimension lengths:
                uint x = (uint)m_TetrisGame.DynamicField.GetLength(0);
                uint y = (uint)m_TetrisGame.DynamicField.GetLength(1);
                fieldNode.ArrayDimensions = new ReadOnlyList <uint>(new uint[] { x, y });
                //add the reference from the Tetris_Game Object Node to this one:
                tetrisGameNode.AddChild(fieldNode);
                //---------------------------------------------------------------

                AddPredefinedNode(SystemContext, tetrisGameNode);
                //---------------------------------------------------------------------------------------------
                #endregion

                #region tetris method node
                //------------------------------ The method node for the tetris game --------------------------

                // ------ The  method state itself: ------
                MethodState pauseMethodNode = new MethodState(tetrisGameNode);
                pauseMethodNode.NodeId          = new NodeId(id++, NamespaceIndex);
                pauseMethodNode.BrowseName      = new QualifiedName("Pause_Method", NamespaceIndex);
                pauseMethodNode.DisplayName     = pauseMethodNode.BrowseName.Name;
                pauseMethodNode.SymbolicName    = pauseMethodNode.BrowseName.Name;
                pauseMethodNode.Description     = new LocalizedText("A method to pause the TetrisGame for X seconds");
                pauseMethodNode.ReferenceTypeId = ReferenceTypeIds.HasComponent;
                pauseMethodNode.UserExecutable  = true;
                pauseMethodNode.Executable      = true;

                // ------ Add the InputArguments: ------
                pauseMethodNode.InputArguments              = new PropertyState <Argument[]>(pauseMethodNode);
                pauseMethodNode.InputArguments.NodeId       = new NodeId(id++, NamespaceIndex);
                pauseMethodNode.InputArguments.BrowseName   = BrowseNames.InputArguments;
                pauseMethodNode.InputArguments.DisplayName  = new LocalizedText("InputArgs_PauseMethod");
                pauseMethodNode.InputArguments.SymbolicName = pauseMethodNode.InputArguments.DisplayName.Text;
                // These are properties of the method state (closer relation with parent than "HasComponent"):
                pauseMethodNode.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType;
                pauseMethodNode.InputArguments.ReferenceTypeId  = ReferenceTypeIds.HasProperty;
                //Attributes related to the Value (= Argument):
                pauseMethodNode.InputArguments.DataType  = DataTypeIds.Argument;
                pauseMethodNode.InputArguments.ValueRank = ValueRanks.Scalar;
                // Create the Argument (= Value of PropertyNode 'InputArguments'):
                Argument[] args_in = new Argument[1]; // only one inputargument
                args_in[0]             = new Argument();
                args_in[0].Name        = "SecondsToPause";
                args_in[0].Description = "The number of seconds to pause the Tetris Game";
                args_in[0].DataType    = DataTypeIds.UInt32;
                args_in[0].ValueRank   = ValueRanks.Scalar;
                // Add the Argument as the Value of the method Node:
                pauseMethodNode.InputArguments.Value = args_in;

                // ------ Add the OutputArguments: ------
                pauseMethodNode.OutputArguments              = new PropertyState <Argument[]>(pauseMethodNode);
                pauseMethodNode.OutputArguments.NodeId       = new NodeId(id++, NamespaceIndex);
                pauseMethodNode.OutputArguments.BrowseName   = BrowseNames.OutputArguments;
                pauseMethodNode.OutputArguments.DisplayName  = new LocalizedText("OutputArgs_PauseMethod");
                pauseMethodNode.OutputArguments.SymbolicName = pauseMethodNode.OutputArguments.DisplayName.Text;
                // These are properties of the method state (closer relation with parent than "HasComponent"):
                pauseMethodNode.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType;
                pauseMethodNode.OutputArguments.ReferenceTypeId  = ReferenceTypeIds.HasProperty;
                //Attributes related to the Value (= Argument):
                pauseMethodNode.OutputArguments.DataType  = DataTypeIds.Argument;
                pauseMethodNode.OutputArguments.ValueRank = ValueRanks.Scalar;
                // Create the Argument (= Value of PropertyNode 'InputArguments'):
                Argument[] args_out = new Argument[1]; // only one outputargument
                args_out[0]             = new Argument();
                args_out[0].Name        = "SecondsToPause_StringResult";
                args_out[0].Description = "A string telling the Nr. of seconds the game is paused";
                args_out[0].DataType    = DataTypeIds.String;
                args_out[0].ValueRank   = ValueRanks.Scalar;
                // Add the Argument as the Value of the method Node:
                pauseMethodNode.OutputArguments.Value = args_out;

                // ------ set up myPauseMethod method handler: ------
                pauseMethodNode.OnCallMethod = new GenericMethodCalledEventHandler(OnPauseMethod);
                // (From now on OnPauseMethod(...) will be called whenever this method is called by the client!)

                // ------ Add the Method Node as child to the Tetris_Game parent node... ------
                tetrisGameNode.AddChild(pauseMethodNode);
                // ------ ... and add it to the predefined nodes: ------
                AddPredefinedNode(SystemContext, pauseMethodNode);

                //---------------------------------------------------------------------------------------------
                #endregion

                #region TetrisLinesMadeEventType
                //----------------Add the TetrisLinesMadeEventType to the EventTYpe Hierarchy -----------------

                // Create the Type information                      (i.e. Object type with attached properties)
                // to represent our TetrisLinesMadeEventType        (with its 2 properties),
                // in the OPC UA type model's EventType Hierarchy   (which is accessible in the server Address Space)

                BaseObjectTypeState newEventType = new BaseObjectTypeState(); // remeber EventTypes are ObjectTypes!
                newEventType.NodeId = ExpandedNodeId.ToNodeId(
                    ObjectTypeIds_TetrisEvents.TetrisLinesMadeEventType,
                    SystemContext.NamespaceUris);                       // the fixed (in 'constants' defined) NodeId is used here!
                newEventType.SuperTypeId = ObjectTypeIds.BaseEventType; // our new EventType will inherit from BaseEventType
                newEventType.BrowseName  = new QualifiedName(BrowseNames_TetrisEvents.TetrisLinesMadeEventType, NamespaceIndex);
                newEventType.DisplayName = new LocalizedText(BrowseNames_TetrisEvents.TetrisLinesMadeEventType);
                newEventType.IsAbstract  = true; // events are NOT nodes in the Address Space (no instances can be made)s

                // Create the two Properties.

                // NrOfLinesMade:
                PropertyState <uint> nrOfLines = new PropertyState <uint>(newEventType);
                nrOfLines.NodeId = ExpandedNodeId.ToNodeId(
                    VariableIds_TetrisEvents.TetrisLinesMadeEventType_NrOfLines,
                    SystemContext.NamespaceUris);
                nrOfLines.BrowseName       = new QualifiedName(BrowseNames_TetrisEvents.NrOfLines, NamespaceIndex);
                nrOfLines.DisplayName      = new LocalizedText(BrowseNames_TetrisEvents.NrOfLines);
                nrOfLines.Description      = new LocalizedText("An unsigned Integer representing the number of lines made in Tetris Game");
                nrOfLines.ReferenceTypeId  = ReferenceTypeIds.HasProperty;
                nrOfLines.TypeDefinitionId = VariableTypeIds.PropertyType;
                nrOfLines.DataType         = DataTypeIds.UInt32;
                nrOfLines.ValueRank        = ValueRanks.Scalar;

                // PointsScored:
                PropertyState <double> pointsScored = new PropertyState <double>(newEventType);
                pointsScored.NodeId = ExpandedNodeId.ToNodeId(
                    VariableIds_TetrisEvents.TetrisLinesMadeEventType_PointsScored,
                    SystemContext.NamespaceUris);
                pointsScored.BrowseName       = new QualifiedName(BrowseNames_TetrisEvents.PointsScored, NamespaceIndex);
                pointsScored.DisplayName      = new LocalizedText(BrowseNames_TetrisEvents.PointsScored);
                pointsScored.Description      = new LocalizedText("A double representing the points scored when making 'NrOfLines' lines");
                pointsScored.ReferenceTypeId  = ReferenceTypeIds.HasProperty;
                pointsScored.TypeDefinitionId = VariableTypeIds.PropertyType;
                pointsScored.DataType         = DataTypeIds.Double;
                pointsScored.ValueRank        = ValueRanks.Scalar;

                // The constants defined in "TetrisEventsConstants.cs" were used above
                // for the creation of the NodeId's, BrowseNames and DisplayNames!

                //Add these two properties as children to the newEventType (= TetrisLinesMadeEventT:ype)
                newEventType.AddChild(pointsScored);
                newEventType.AddChild(nrOfLines);

                // ...And add newEventType (= TetrisLinesMadeEventType) it to the predefined nodes:
                AddPredefinedNode(SystemContext, newEventType); // will also add the new type to the Type Hierarchy!
                //---------------------------------------------------------------------------------------------
                #endregion

                //------------------------ Initialize UpdateTimer---------------------------
                m_UpdateTimer = new Timer(UpdateTimerCallback, null, 1000, 500);
                //--------------------------------------------------------------------------
            }
        }