/// <summary> /// Returns a snapshot of the tags belonging to the block. /// </summary> /// <returns>The list of tags. Null if the block does not exist.</returns> public IList <UnderlyingSystemTag> GetTags() { lock (_tags) { // create snapshots of the tags. var tags = new UnderlyingSystemTag[_tags.Count]; for (var ii = 0; ii < _tags.Count; ii++) { tags[ii] = _tags[ii].CreateSnapshot(); } return(tags); } }
/// <summary> /// Updates the metadata for a tag. /// </summary> private bool UpdateTagMetadata( UnderlyingSystemTag tag, Opc.Ua.Test.TestDataGenerator generator) { switch (tag.TagType) { case UnderlyingSystemTagType.Analog: { if (tag.EuRange != null) { var range = new double[tag.EuRange.Length]; for (var ii = 0; ii < tag.EuRange.Length; ii++) { range[ii] = tag.EuRange[ii] + 1; } tag.EuRange = range; } break; } case UnderlyingSystemTagType.Digital: case UnderlyingSystemTagType.Enumerated: { if (tag.Labels != null) { var labels = new string[tag.Labels.Length]; for (var ii = 0; ii < tag.Labels.Length; ii++) { labels[ii] = generator.GetRandomString(); } tag.Labels = labels; } break; } default: { return(false); } } return(true); }
/// <summary> /// Updates a variable from a tag. /// </summary> /// <param name="context">The context.</param> /// <param name="tag">The tag.</param> /// <param name="variable">The variable to update.</param> private void UpdateVariable(ISystemContext context, UnderlyingSystemTag tag, BaseVariableState variable) { System.Diagnostics.Contracts.Contract.Assume(context != null); variable.Description = tag.Description; variable.Value = tag.Value; variable.Timestamp = tag.Timestamp; switch (tag.DataType) { case UnderlyingSystemDataType.Integer1: { variable.DataType = DataTypes.SByte; break; } case UnderlyingSystemDataType.Integer2: { variable.DataType = DataTypes.Int16; break; } case UnderlyingSystemDataType.Integer4: { variable.DataType = DataTypes.Int32; break; } case UnderlyingSystemDataType.Real4: { variable.DataType = DataTypes.Float; break; } case UnderlyingSystemDataType.String: { variable.DataType = DataTypes.String; break; } } variable.ValueRank = ValueRanks.Scalar; variable.ArrayDimensions = null; if (tag.IsWriteable) { variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; } else { variable.AccessLevel = AccessLevels.CurrentRead; variable.UserAccessLevel = AccessLevels.CurrentRead; } variable.MinimumSamplingInterval = MinimumSamplingIntervals.Continuous; variable.Historizing = false; switch (tag.TagType) { case UnderlyingSystemTagType.Analog: { var node = variable as AnalogItemState; if (tag.EuRange != null) { if (tag.EuRange.Length >= 2 && node.EURange != null) { var range = new Range(tag.EuRange[0], tag.EuRange[1]); node.EURange.Value = range; node.EURange.Timestamp = tag.Block.Timestamp; } if (tag.EuRange.Length >= 4 && node.InstrumentRange != null) { var range = new Range(tag.EuRange[2], tag.EuRange[3]); node.InstrumentRange.Value = range; node.InstrumentRange.Timestamp = tag.Block.Timestamp; } } if (!string.IsNullOrEmpty(tag.EngineeringUnits) && node.EngineeringUnits != null) { var info = new EUInformation { DisplayName = tag.EngineeringUnits, NamespaceUri = Namespaces.DataAccess }; node.EngineeringUnits.Value = info; node.EngineeringUnits.Timestamp = tag.Block.Timestamp; } break; } case UnderlyingSystemTagType.Digital: { var node = variable as TwoStateDiscreteState; if (tag.Labels != null && node.TrueState != null && node.FalseState != null) { if (tag.Labels.Length >= 2) { node.TrueState.Value = new LocalizedText(tag.Labels[0]); node.TrueState.Timestamp = tag.Block.Timestamp; node.FalseState.Value = new LocalizedText(tag.Labels[1]); node.FalseState.Timestamp = tag.Block.Timestamp; } } break; } case UnderlyingSystemTagType.Enumerated: { var node = variable as MultiStateDiscreteState; if (tag.Labels != null) { var strings = new LocalizedText[tag.Labels.Length]; for (var ii = 0; ii < tag.Labels.Length; ii++) { strings[ii] = new LocalizedText(tag.Labels[ii]); } node.EnumStrings.Value = strings; node.EnumStrings.Timestamp = tag.Block.Timestamp; } break; } } }
/// <summary> /// Creates a variable from a tag. /// </summary> /// <param name="context">The context.</param> /// <param name="tag">The tag.</param> /// <returns>The variable that represents the tag.</returns> private BaseVariableState CreateVariable(ISystemContext context, UnderlyingSystemTag tag) { // create the variable type based on the tag type. BaseDataVariableState variable = null; switch (tag.TagType) { case UnderlyingSystemTagType.Analog: { var node = new AnalogItemState(this); if (tag.EngineeringUnits != null) { node.EngineeringUnits = new PropertyState <EUInformation>(node); } if (tag.EuRange.Length >= 4) { node.InstrumentRange = new PropertyState <Range>(node); } variable = node; break; } case UnderlyingSystemTagType.Digital: { var node = new TwoStateDiscreteState(this); variable = node; break; } case UnderlyingSystemTagType.Enumerated: { var node = new MultiStateDiscreteState(this); if (tag.Labels != null) { node.EnumStrings = new PropertyState <LocalizedText[]>(node); } variable = node; break; } default: { var node = new DataItemState(this); variable = node; break; } } // set the symbolic name and reference types. variable.SymbolicName = tag.Name; variable.ReferenceTypeId = ReferenceTypeIds.HasComponent; // initialize the variable from the type model. variable.Create( context, null, new QualifiedName(tag.Name, BrowseName.NamespaceIndex), null, true); // update the variable values. UpdateVariable(context, tag, variable); return(variable); }
/// <summary> /// Creates the tag. /// </summary> /// <param name="tagName">Name of the tag.</param> /// <param name="dataType">Type of the data.</param> /// <param name="tagType">Type of the tag.</param> /// <param name="engineeringUnits">The engineering units.</param> /// <param name="writeable">if set to <c>true</c> the tag is writeable.</param> public void CreateTag( string tagName, UnderlyingSystemDataType dataType, UnderlyingSystemTagType tagType, string engineeringUnits, bool writeable) { // create tag. var tag = new UnderlyingSystemTag { Block = this, Name = tagName, Description = null, EngineeringUnits = engineeringUnits, DataType = dataType, TagType = tagType, IsWriteable = writeable, Labels = null, EuRange = null }; switch (tagType) { case UnderlyingSystemTagType.Analog: { tag.Description = "An analog value."; tag.TagType = UnderlyingSystemTagType.Analog; tag.EuRange = new double[] { 100, 0 }; break; } case UnderlyingSystemTagType.Digital: { tag.Description = "A digital value."; tag.TagType = UnderlyingSystemTagType.Digital; tag.Labels = new string[] { "Online", "Offline" }; break; } case UnderlyingSystemTagType.Enumerated: { tag.Description = "An enumerated value."; tag.TagType = UnderlyingSystemTagType.Enumerated; tag.Labels = new string[] { "Red", "Yellow", "Green" }; break; } default: { tag.Description = "A generic value."; break; } } // set an initial value. switch (tag.DataType) { case UnderlyingSystemDataType.Integer1: { tag.Value = (sbyte)0; break; } case UnderlyingSystemDataType.Integer2: { tag.Value = (short)0; break; } case UnderlyingSystemDataType.Integer4: { tag.Value = 0; break; } case UnderlyingSystemDataType.Real4: { tag.Value = (float)0; break; } case UnderlyingSystemDataType.String: { tag.Value = string.Empty; break; } } lock (_tags) { _tags.Add(tag); Timestamp = DateTime.UtcNow; } }
/// <summary> /// Updates the value of an tag. /// </summary> private bool UpdateTagValue( UnderlyingSystemTag tag, Opc.Ua.Test.TestDataGenerator generator) { // don't update writeable tags. if (tag.IsWriteable) { return(false); } // check if a range applies to the value. var high = 0; var low = 0; switch (tag.TagType) { case UnderlyingSystemTagType.Analog: { if (tag.EuRange?.Length >= 2) { high = (int)tag.EuRange[0]; low = (int)tag.EuRange[1]; } break; } case UnderlyingSystemTagType.Digital: { high = 1; low = 0; break; } case UnderlyingSystemTagType.Enumerated: { if (tag.Labels?.Length > 0) { high = tag.Labels.Length - 1; low = 0; } break; } } // select a value in the range. var value = -1; if (high > low) { value = (generator.GetRandomUInt16() % (high - low + 1)) + low; } // cast value to correct type or generate a random value. switch (tag.DataType) { case UnderlyingSystemDataType.Integer1: { if (value == -1) { tag.Value = generator.GetRandomSByte(); } else { tag.Value = (sbyte)value; } break; } case UnderlyingSystemDataType.Integer2: { if (value == -1) { tag.Value = generator.GetRandomInt16(); } else { tag.Value = (short)value; } break; } case UnderlyingSystemDataType.Integer4: { if (value == -1) { tag.Value = generator.GetRandomInt32(); } else { tag.Value = value; } break; } case UnderlyingSystemDataType.Real4: { if (value == -1) { tag.Value = generator.GetRandomFloat(); } else { tag.Value = (float)value; } break; } case UnderlyingSystemDataType.String: { tag.Value = generator.GetRandomString(); break; } } tag.Timestamp = DateTime.UtcNow; return(true); }
/// <summary> /// Writes the tag value. /// </summary> /// <param name="tagName">Name of the tag.</param> /// <param name="value">The value.</param> /// <returns>The status code for the operation.</returns> public uint WriteTagValue(string tagName, object value) { UnderlyingSystemTag tag = null; TagsChangedEventHandler onTagsChanged = null; lock (_tags) { onTagsChanged = _onTagsChanged; // find the tag. tag = FindTag(tagName); if (tag == null) { return(StatusCodes.BadNodeIdUnknown); } // cast value to correct type. try { switch (tag.DataType) { case UnderlyingSystemDataType.Integer1: { tag.Value = (sbyte)value; break; } case UnderlyingSystemDataType.Integer2: { tag.Value = (short)value; break; } case UnderlyingSystemDataType.Integer4: { tag.Value = (int)value; break; } case UnderlyingSystemDataType.Real4: { tag.Value = (float)value; break; } case UnderlyingSystemDataType.String: { tag.Value = (string)value; break; } } } catch { return(StatusCodes.BadTypeMismatch); } // updated the timestamp. tag.Timestamp = DateTime.UtcNow; } // raise notification. if (tag != null && onTagsChanged != null) { onTagsChanged(new UnderlyingSystemTag[] { tag }); } return(StatusCodes.Good); }