예제 #1
0
        /// <summary>
        /// Handles a method call.
        /// </summary>
        private ServiceResult DoGenerateRandomValues(
            ISystemContext context,
            MethodState method,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle;
            ComDaClient        client = system.SelectClient((ServerSystemContext)context, false);

            Opc.Ua.Test.DataGenerator generator = new Opc.Ua.Test.DataGenerator(null);

            IDaElementBrowser browser = client.CreateBrowser((string)method.Handle);

            // create write requests.
            WriteRequestCollection requests = new WriteRequestCollection();

            try
            {
                for (DaElement element = browser.Next(); element != null; element = browser.Next())
                {
                    if (element.ElementType == DaElementType.Branch)
                    {
                        continue;
                    }

                    // generate a random value of the correct data tyoe.
                    bool   isArray    = false;
                    NodeId dataTypeId = ComUtils.GetDataTypeId(element.DataType, out isArray);

                    object value = generator.GetRandom(
                        dataTypeId,
                        (isArray)?ValueRanks.OneDimension:ValueRanks.Scalar,
                        null,
                        context.TypeTable);

                    // create a request.
                    requests.Add(new Opc.Ua.Com.Client.WriteRequest(element.ItemId, new DataValue(new Variant(value)), 0));
                }
            }
            finally
            {
                browser.Dispose();
            }

            // write values.
            client.Write(requests);

            return(ServiceResult.Good);
        }
예제 #2
0
        /// <summary>
        /// Initializes the node from the element.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="itemId">The item id.</param>
        /// <param name="property">The property.</param>
        /// <param name="namespaceIndex">Index of the namespace.</param>
        public void Initialize(ISystemContext context, string itemId, DaProperty property, ushort namespaceIndex)
        {
            m_itemId   = itemId;
            m_property = property;

            if (property == null)
            {
                return;
            }

            this.NodeId           = ModelUtils.ConstructIdForDaElement(m_itemId, property.PropertyId, namespaceIndex);
            this.BrowseName       = new QualifiedName(property.Name, namespaceIndex);
            this.DisplayName      = new LocalizedText(property.Name);
            this.TypeDefinitionId = Opc.Ua.VariableTypeIds.PropertyType;
            this.Value            = null;
            this.StatusCode       = StatusCodes.BadWaitingForInitialData;
            this.Timestamp        = DateTime.UtcNow;

            bool isArray = false;

            this.DataType        = ComUtils.GetDataTypeId(property.DataType, out isArray);
            this.ValueRank       = (isArray)?ValueRanks.OneOrMoreDimensions:ValueRanks.Scalar;
            this.ArrayDimensions = null;

            // assume that properties with item ids are writeable. the server may still reject the write.
            if (String.IsNullOrEmpty(property.ItemId))
            {
                this.AccessLevel = AccessLevels.CurrentRead;
            }
            else
            {
                this.AccessLevel = AccessLevels.CurrentReadOrWrite;
            }

            this.UserAccessLevel         = this.AccessLevel;
            this.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate;
            this.Historizing             = false;

            // add a reference to the parent node.
            NodeId parentNodeId = ModelUtils.ConstructIdForDaElement(itemId, -1, namespaceIndex);

            this.AddReference(ReferenceTypeIds.HasProperty, true, parentNodeId);
        }
예제 #3
0
        /// <summary>
        /// Validates the items.
        /// </summary>
        /// <param name="group">The group.</param>
        /// <param name="requests">The requests.</param>
        /// <returns>The items. May contain null is validation failed.</returns>
        public ComDaGroupItem[] ValidateItems(ComDaGroup group, ComDaCreateItemRequest[] requests)
        {
            TraceState("ValidateItems", group.Name);

            // get the session to use for the operation.
            Session session = m_session;

            if (session == null)
            {
                throw ComUtils.CreateComException(ResultIds.E_FAIL);
            }

            // validate items.
            ComDaGroupItem[] items = new ComDaGroupItem[requests.Length];

            for (int ii = 0; ii < requests.Length; ii += 10000)
            {
                ValidateItems(session, group, requests, items, ii, 10000);
            }

            // process results.
            for (int ii = 0; ii < requests.Length; ii++)
            {
                // check for the results.
                ComDaCreateItemRequest request = requests[ii];

                if (request.Error < 0)
                {
                    items[ii] = null;
                    continue;
                }

                // check access path.
                if (!String.IsNullOrEmpty(request.AccessPath))
                {
                    items[ii]     = null;
                    request.Error = ResultIds.E_UNKNOWNPATH;
                    continue;
                }

                ComDaGroupItem item = items[ii];

                // validate the datatype.
                if (request.RequestedDataType != 0)
                {
                    NodeId dataTypeId = ComUtils.GetDataTypeId(request.RequestedDataType);

                    if (NodeId.IsNull(dataTypeId))
                    {
                        items[ii]     = null;
                        request.Error = ResultIds.E_BADTYPE;
                        continue;
                    }

                    bool reqTypeIsArray    = (request.RequestedDataType & (short)VarEnum.VT_ARRAY) != 0;
                    bool actualTypeIsArray = (item.CanonicalDataType & (short)VarEnum.VT_ARRAY) != 0;

                    if (reqTypeIsArray != actualTypeIsArray)
                    {
                        items[ii]     = null;
                        request.Error = ResultIds.E_BADTYPE;
                        continue;
                    }
                }

                // create a new monitored item.
                MonitoredItem monitoredItem = new MonitoredItem();

                monitoredItem.StartNodeId      = item.NodeId;
                monitoredItem.RelativePath     = null;
                monitoredItem.AttributeId      = Attributes.Value;
                monitoredItem.MonitoringMode   = (request.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled;
                monitoredItem.SamplingInterval = group.UpdateRate / 2;
                monitoredItem.QueueSize        = 0;
                monitoredItem.DiscardOldest    = true;
                monitoredItem.Filter           = null;

                // update item.
                item.ServerHandle  = (int)monitoredItem.ClientHandle;
                item.MonitoredItem = monitoredItem;

                // link the monitored item back to the group item.
                monitoredItem.Handle = item;

                // update return parameters.
                request.ServerHandle      = item.ServerHandle;
                request.CanonicalDataType = item.CanonicalDataType;
                request.AccessRights      = item.AccessRights;
                request.Error             = ResultIds.S_OK;
            }

            return(items);
        }
예제 #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AeEventTypeState"/> class.
        /// </summary>
        public AeEventTypeState(EventType eventType, ushort namespaceIndex)
        {
            m_eventType = eventType;

            // create the name for the event type.
            string name = eventType.Description;

            if (!String.IsNullOrEmpty(eventType.ConditionName))
            {
                name = eventType.ConditionName;
            }

            if (!name.EndsWith("Type"))
            {
                if (eventType.EventTypeId == OpcRcw.Ae.Constants.CONDITION_EVENT)
                {
                    name += "AlarmType";
                }
                else
                {
                    name += "EventType";
                }
            }

            // the attributes.
            this.NodeId      = AeParsedNodeId.Construct(eventType, null, namespaceIndex);
            this.BrowseName  = new QualifiedName(name, namespaceIndex);
            this.DisplayName = eventType.Description;
            this.IsAbstract  = false;
            this.SuperTypeId = AeParsedNodeId.Construct(eventType.EventTypeMapping, namespaceIndex);

            // add the attributes as properties.
            if (eventType.Attributes != null)
            {
                for (int ii = 0; ii < eventType.Attributes.Count; ii++)
                {
                    string propertyName = eventType.Attributes[ii].Description;

                    if (AeTypeCache.IsKnownName(propertyName, "ACK COMMENT"))
                    {
                        continue;
                    }

                    PropertyState property = new PropertyState(this);

                    property.SymbolicName            = propertyName;
                    property.ReferenceTypeId         = Opc.Ua.ReferenceTypeIds.HasProperty;
                    property.TypeDefinitionId        = Opc.Ua.VariableTypeIds.PropertyType;
                    property.ModellingRuleId         = Opc.Ua.ObjectIds.ModellingRule_Optional;
                    property.NodeId                  = AeParsedNodeId.Construct(eventType, propertyName, namespaceIndex);
                    property.BrowseName              = new QualifiedName(propertyName, namespaceIndex);
                    property.DisplayName             = property.BrowseName.Name;
                    property.AccessLevel             = AccessLevels.None;
                    property.UserAccessLevel         = AccessLevels.None;
                    property.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate;
                    property.Historizing             = false;

                    bool isArray = false;
                    property.DataType  = ComUtils.GetDataTypeId(eventType.Attributes[ii].VarType, out isArray);
                    property.ValueRank = (isArray) ? ValueRanks.OneDimension : ValueRanks.Scalar;

                    this.AddChild(property);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Gets the result for the read operayoin.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="item">The item.</param>
        /// <param name="nodeToRead">The node to read.</param>
        /// <param name="value">The value.</param>
        /// <param name="diagnosticsMasks">The diagnostics masks.</param>
        /// <returns></returns>
        public ServiceResult GetResult(
            ISystemContext context,
            DaItemState item,
            ReadValueId nodeToRead,
            DataValue value,
            DiagnosticsMasks diagnosticsMasks)
        {
            if (nodeToRead.AttributeId == Attributes.Value)
            {
                ServiceResult result = GetItemValue(m_value, value, diagnosticsMasks);

                if (ServiceResult.IsBad(result))
                {
                    return(result);
                }

                return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value));
            }

            switch (nodeToRead.AttributeId)
            {
            case Attributes.Description:
            {
                string description = this.GetPropertyValue <string>(Opc.Ua.Com.PropertyIds.Description, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = new LocalizedText(description);
                }

                break;
            }

            case Attributes.DataType:
            {
                short datatype = this.GetPropertyValue <short>(Opc.Ua.Com.PropertyIds.DataType, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = ComUtils.GetDataTypeId(datatype);
                }

                break;
            }

            case Attributes.ValueRank:
            {
                short datatype = this.GetPropertyValue <short>(Opc.Ua.Com.PropertyIds.DataType, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = ComUtils.GetValueRank(datatype);
                }

                break;
            }

            case Attributes.AccessLevel:
            case Attributes.UserAccessLevel:
            {
                int accessRights = this.GetPropertyValue <int>(Opc.Ua.Com.PropertyIds.AccessRights, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = (byte)accessRights;
                }

                break;
            }

            case Attributes.MinimumSamplingInterval:
            {
                float scanRate = this.GetPropertyValue <float>(Opc.Ua.Com.PropertyIds.ScanRate, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = (double)scanRate;
                }

                break;
            }

            default:
            {
                return(StatusCodes.BadAttributeIdInvalid);
            }
            }

            // check if the property value is missing.
            if (value.StatusCode == StatusCodes.BadNotFound)
            {
                return(StatusCodes.BadAttributeIdInvalid);
            }

            return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value));
        }
예제 #6
0
        /// <summary>
        /// Initializes the node from the element.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="element">The element.</param>
        /// <param name="namespaceIndex">Index of the namespace.</param>
        public void Initialize(ISystemContext context, DaElement element, ushort namespaceIndex)
        {
            m_element = element;

            if (element == null)
            {
                return;
            }

            this.NodeId      = DaModelUtils.ConstructIdForDaElement(element.ItemId, -1, namespaceIndex);
            this.BrowseName  = new QualifiedName(element.Name, namespaceIndex);
            this.DisplayName = new LocalizedText(element.Name);

            // check if TimeZone is supported.
            if (element.TimeZone != null)
            {
                PropertyState property = this.AddProperty <Range>(Opc.Ua.BrowseNames.LocalTime, DataTypeIds.TimeZoneDataType, ValueRanks.Scalar);
                property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex);
                property.Value  = new Range(element.HighIR, element.LowIR);
            }

            // set the TypeDefinition based on the ElementType.
            switch (element.ElementType)
            {
            case DaElementType.AnalogItem:
            {
                this.TypeDefinitionId = Opc.Ua.VariableTypeIds.AnalogItemType;

                // EURange is always present.
                PropertyState property = this.AddProperty <Range>(Opc.Ua.BrowseNames.EURange, DataTypeIds.Range, ValueRanks.Scalar);
                property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex);
                property.Value  = new Range(element.HighEU, element.LowEU);

                // check if InstrumentRange is supported.
                if (element.HighIR != 0 || element.LowIR != 0)
                {
                    property        = this.AddProperty <Range>(Opc.Ua.BrowseNames.InstrumentRange, DataTypeIds.Range, ValueRanks.Scalar);
                    property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex);
                    property.Value  = new Range(element.HighIR, element.LowIR);
                }

                // check if EngineeringUnits is supported.
                if (element.EngineeringUnits != null)
                {
                    property        = this.AddProperty <EUInformation>(Opc.Ua.BrowseNames.EngineeringUnits, DataTypeIds.EUInformation, ValueRanks.Scalar);
                    property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex);

                    // use the server's namespace uri to qualify the engineering units.
                    string namespaceUri = context.NamespaceUris.GetString(namespaceIndex);
                    property.Value = new EUInformation(element.EngineeringUnits, namespaceUri);
                }

                break;
            }

            case DaElementType.DigitalItem:
            {
                this.TypeDefinitionId = Opc.Ua.VariableTypeIds.TwoStateDiscreteType;

                // check if CloseLabel is supported.
                if (element.CloseLabel != null)
                {
                    PropertyState property = this.AddProperty <LocalizedText>(Opc.Ua.BrowseNames.TrueState, DataTypeIds.LocalizedText, ValueRanks.Scalar);
                    property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex);
                    property.Value  = element.CloseLabel;
                }

                // check if OpenLabel is supported.
                if (element.OpenLabel != null)
                {
                    PropertyState property = this.AddProperty <LocalizedText>(Opc.Ua.BrowseNames.FalseState, DataTypeIds.LocalizedText, ValueRanks.Scalar);
                    property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex);
                    property.Value  = element.OpenLabel;
                }

                break;
            }

            case DaElementType.EnumeratedItem:
            {
                this.TypeDefinitionId = Opc.Ua.VariableTypeIds.MultiStateDiscreteType;

                // check if EuInfo is supported.
                if (element.EuInfo != null)
                {
                    PropertyState property = this.AddProperty <LocalizedText[]>(Opc.Ua.BrowseNames.EnumStrings, DataTypeIds.LocalizedText, ValueRanks.OneDimension);
                    property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex);

                    LocalizedText[] strings = new LocalizedText[element.EuInfo.Length];

                    for (int ii = 0; ii < strings.Length; ii++)
                    {
                        strings[ii] = element.EuInfo[ii];
                    }

                    property.Value = strings;
                }

                break;
            }
            }

            if (element.Description != null)
            {
                this.Description = element.Description;
            }

            this.Value      = null;
            this.StatusCode = StatusCodes.BadWaitingForInitialData;
            this.Timestamp  = DateTime.UtcNow;

            bool isArray = false;

            this.DataType  = ComUtils.GetDataTypeId(element.DataType, out isArray);
            this.ValueRank = (isArray)?ValueRanks.OneOrMoreDimensions:ValueRanks.Scalar;

            this.AccessLevel = AccessLevels.None;

            if ((element.AccessRights & OpcRcw.Da.Constants.OPC_READABLE) != 0)
            {
                this.AccessLevel |= AccessLevels.CurrentRead;
            }

            if ((element.AccessRights & OpcRcw.Da.Constants.OPC_WRITEABLE) != 0)
            {
                this.AccessLevel |= AccessLevels.CurrentWrite;
            }

            this.UserAccessLevel         = this.AccessLevel;
            this.MinimumSamplingInterval = element.ScanRate;
        }
예제 #7
0
        /// <summary>
        /// Gets the result for the read operayoin.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="item">The item.</param>
        /// <param name="nodeToRead">The node to read.</param>
        /// <param name="value">The value.</param>
        /// <param name="diagnosticsMasks">The diagnostics masks.</param>
        /// <returns></returns>
        public ServiceResult GetResult(
            ISystemContext context,
            HdaItemState item,
            ReadValueId nodeToRead,
            DataValue value,
            DiagnosticsMasks diagnosticsMasks)
        {
            switch (nodeToRead.AttributeId)
            {
            case Attributes.Description:
            {
                string description = this.GetAttributeValue <string>(Constants.OPCHDA_DESCRIPTION, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = new LocalizedText(description);
                }

                break;
            }

            case Attributes.DataType:
            {
                short datatype = this.GetAttributeValue <short>(Constants.OPCHDA_DATA_TYPE, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = ComUtils.GetDataTypeId(datatype);
                }
                else
                {
                    value.Value      = DataTypeIds.BaseDataType;
                    value.StatusCode = StatusCodes.GoodLocalOverride;
                }

                break;
            }

            case Attributes.ValueRank:
            {
                short datatype = this.GetAttributeValue <short>(Constants.OPCHDA_DATA_TYPE, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = ComUtils.GetValueRank(datatype);
                }
                else
                {
                    value.Value      = ValueRanks.Any;
                    value.StatusCode = StatusCodes.GoodLocalOverride;
                }

                break;
            }

            case Attributes.Historizing:
            {
                bool archiving = this.GetAttributeValue <bool>(Constants.OPCHDA_ARCHIVING, value, false);

                if (StatusCode.IsGood(value.StatusCode))
                {
                    value.Value = archiving;
                }
                else
                {
                    value.Value      = false;
                    value.StatusCode = StatusCodes.GoodLocalOverride;
                }

                break;
            }

            default:
            {
                return(StatusCodes.BadAttributeIdInvalid);
            }
            }

            // check if the attribute value is missing.
            if (value.StatusCode == StatusCodes.BadNotFound)
            {
                return(StatusCodes.BadAttributeIdInvalid);
            }

            return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value));
        }
예제 #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DaItemState"/> class.
        /// </summary>
        /// <param name="configuration">The configuration.</param>
        /// <param name="itemId">The item id.</param>
        /// <param name="attribute">The attribute.</param>
        /// <param name="namespaceIndex">Index of the namespace.</param>
        public HdaAttributeState(
            ComHdaClientConfiguration configuration,
            string itemId,
            HdaAttribute attribute,
            ushort namespaceIndex)
            :
            base(null)
        {
            m_itemId    = itemId;
            m_attribute = attribute;

            this.NodeId                  = HdaModelUtils.ConstructIdForHdaItemAttribute(itemId, attribute.Id, namespaceIndex);
            this.SymbolicName            = attribute.Id.ToString();
            this.Description             = attribute.Description;
            this.AccessLevel             = AccessLevels.CurrentRead;
            this.UserAccessLevel         = AccessLevels.CurrentRead;
            this.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate;
            this.Historizing             = false;
            this.ReferenceTypeId         = Opc.Ua.ReferenceTypeIds.HasProperty;
            this.TypeDefinitionId        = Opc.Ua.VariableTypeIds.PropertyType;
            this.Value      = null;
            this.StatusCode = StatusCodes.BadWaitingForInitialData;

            bool isConfigItem = false;

            // handle built-in properties.
            switch (attribute.Id)
            {
            default:
            {
                bool isArray = false;
                this.BrowseName  = new QualifiedName(this.SymbolicName, namespaceIndex);
                this.DisplayName = attribute.Name;
                this.DataType    = ComUtils.GetDataTypeId(attribute.DataType, out isArray);
                this.ValueRank   = (isArray)?ValueRanks.OneDimension:ValueRanks.Scalar;
                break;
            }

            case Constants.OPCHDA_ENG_UNITS:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.EngineeringUnits;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.EUInformation;
                this.ValueRank   = ValueRanks.Scalar;
                break;
            }

            case Constants.OPCHDA_NORMAL_MAXIMUM:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.EURange;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Range;
                this.ValueRank   = ValueRanks.Scalar;
                break;
            }

            case Constants.OPCHDA_HIGH_ENTRY_LIMIT:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.InstrumentRange;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Range;
                this.ValueRank   = ValueRanks.Scalar;
                break;
            }

            case Constants.OPCHDA_STEPPED:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.Stepped;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Boolean;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_DERIVE_EQUATION:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.Definition;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.String;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_MIN_TIME_INT:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.MinTimeInterval;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Duration;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_MAX_TIME_INT:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.MaxTimeInterval;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Duration;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_EXCEPTION_DEV:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.ExceptionDeviation;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.Double;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }

            case Constants.OPCHDA_EXCEPTION_DEV_TYPE:
            {
                this.BrowseName  = Opc.Ua.BrowseNames.ExceptionDeviationFormat;
                this.DisplayName = this.BrowseName.Name;
                this.DataType    = Opc.Ua.DataTypeIds.ExceptionDeviationFormat;
                this.ValueRank   = ValueRanks.Scalar;
                isConfigItem     = true;
                break;
            }
            }

            // set the parent id.
            NodeId parentId = null;

            if (isConfigItem)
            {
                parentId = HdaParsedNodeId.Construct(HdaModelUtils.HdaItemConfiguration, itemId, null, namespaceIndex);
            }
            else
            {
                parentId = HdaModelUtils.ConstructIdForHdaItem(itemId, namespaceIndex);
            }

            this.AddReference(ReferenceTypeIds.HasProperty, true, parentId);
        }