/// <summary> /// Creates a new instance of a item. /// </summary> public ArchiveItemState(ISystemContext context, ArchiveItem item, ushort namespaceIndex) : base(null) { m_archiveItem = item; this.TypeDefinitionId = VariableTypeIds.DataItemType; this.SymbolicName = m_archiveItem.Name; this.NodeId = ConstructId(m_archiveItem.UniquePath, namespaceIndex); this.BrowseName = new QualifiedName(m_archiveItem.Name, namespaceIndex); this.DisplayName = new LocalizedText(this.BrowseName.Name); this.Description = null; this.WriteMask = 0; this.UserWriteMask = 0; this.DataType = DataTypeIds.BaseDataType; this.ValueRank = ValueRanks.Scalar; this.AccessLevel = AccessLevels.HistoryReadOrWrite | AccessLevels.CurrentRead; this.UserAccessLevel = AccessLevels.HistoryReadOrWrite | AccessLevels.CurrentRead; this.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; this.Historizing = true; m_annotations = new PropertyState<Annotation>(this); m_annotations.ReferenceTypeId = ReferenceTypeIds.HasProperty; m_annotations.TypeDefinitionId = VariableTypeIds.PropertyType; m_annotations.SymbolicName = Opc.Ua.BrowseNames.Annotations; m_annotations.BrowseName = Opc.Ua.BrowseNames.Annotations; m_annotations.DisplayName = new LocalizedText(m_annotations.BrowseName.Name); m_annotations.Description = null; m_annotations.WriteMask = 0; m_annotations.UserWriteMask = 0; m_annotations.DataType = DataTypeIds.Annotation; m_annotations.ValueRank = ValueRanks.Scalar; m_annotations.AccessLevel = AccessLevels.HistoryReadOrWrite; m_annotations.UserAccessLevel = AccessLevels.HistoryReadOrWrite; m_annotations.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; m_annotations.Historizing = false; this.AddChild(m_annotations); m_annotations.NodeId = NodeTypes.ConstructIdForComponent(m_annotations, namespaceIndex); m_configuration = new HistoricalDataConfigurationState(this); m_configuration.MaxTimeInterval = new PropertyState<double>(m_configuration); m_configuration.MinTimeInterval = new PropertyState<double>(m_configuration); ; m_configuration.StartOfArchive = new PropertyState<DateTime>(m_configuration); m_configuration.StartOfOnlineArchive = new PropertyState<DateTime>(m_configuration); m_configuration.Create( context, null, Opc.Ua.BrowseNames.HAConfiguration, null, true); m_configuration.SymbolicName = Opc.Ua.BrowseNames.HAConfiguration; m_configuration.ReferenceTypeId = ReferenceTypeIds.HasHistoricalConfiguration; this.AddChild(m_configuration); }
/// <summary> /// Returns a item object for the specified node. /// </summary> public ArchiveItemState GetItemState(ISystemContext context, ParsedNodeId parsedNodeId) { if (parsedNodeId.RootType != NodeTypes.Item) { return null; } StringBuilder path = new StringBuilder(); path.Append(m_configuration.ArchiveRoot); path.Append('/'); path.Append(parsedNodeId.RootId); ArchiveItem item = new ArchiveItem(parsedNodeId.RootId, new FileInfo(path.ToString())); return new ArchiveItemState(context, item, m_namespaceIndex); }
static void DoTest(TestCase test, string filePath) { List <DataValue> expectedValues = GetExpectedResults(test.ExpectedResultsPath, test.TestId); ArchiveItem item = new ArchiveItem(test.DataPath, Assembly.GetExecutingAssembly(), test.DataPath); DataFileReader reader = new DataFileReader(); reader.LoadConfiguration(null, item); reader.LoadHistoryData(null, item); AggregateConfiguration configuration = new AggregateConfiguration(); configuration.PercentDataBad = 100; configuration.PercentDataGood = 100; configuration.TreatUncertainAsBad = test.TreatUncertainAsBad; configuration.UseSlopedExtrapolation = test.UseSlopedExtrapolation; configuration.UseServerCapabilitiesDefaults = false; DateTime startTime = DateTime.UtcNow; startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0, DateTimeKind.Utc); AggregateCalculator calculator = new AggregateCalculator( test.AggregateId, startTime.AddSeconds(0), startTime.AddSeconds(100), 5000, test.Stepped, configuration); StringBuilder buffer = new StringBuilder(); List <DataValue> values = new List <DataValue>(); foreach (DataRowView row in item.DataSet.Tables[0].DefaultView) { DataValue rawValue = (DataValue)row.Row[2]; if (!calculator.QueueRawValue(rawValue)) { Utils.Trace("Oops!"); continue; } DataValue processedValue = calculator.GetProcessedValue(false); if (processedValue != null) { values.Add(processedValue); } } for (DataValue processedValue = calculator.GetProcessedValue(true); processedValue != null; processedValue = calculator.GetProcessedValue(true)) { values.Add(processedValue); } for (int ii = 0; ii < values.Count && ii < expectedValues.Count; ii++) { if (values[ii].SourceTimestamp != expectedValues[ii].SourceTimestamp) { Utils.Trace("Wrong Status Timestamp"); continue; } if (values[ii].StatusCode != expectedValues[ii].StatusCode) { Utils.Trace("Wrong Status Code"); continue; } if (StatusCode.IsNotBad(values[ii].StatusCode)) { double value1 = Math.Round(Convert.ToDouble(values[ii].Value), 4); double value2 = Math.Round(Convert.ToDouble(expectedValues[ii].Value), 4); if (value1 != value2) { Utils.Trace("Wrong Value"); continue; } } } foreach (DataValue processedValue in values) { buffer.Append(processedValue.SourceTimestamp.ToString("HH:mm:ss")); buffer.Append(", "); buffer.Append(processedValue.WrappedValue); buffer.Append(", "); buffer.Append(new StatusCode(processedValue.StatusCode.CodeBits)); buffer.Append(", "); buffer.Append(processedValue.StatusCode.AggregateBits); buffer.Append("\r\n"); } // write to the file. using (StreamWriter writer = new StreamWriter(filePath)) { writer.Write(buffer.ToString()); } }
static void DoTest(TestCase test, string filePath) { List<DataValue> expectedValues = GetExpectedResults(test.ExpectedResultsPath, test.TestId); ArchiveItem item = new ArchiveItem(test.DataPath, Assembly.GetExecutingAssembly(), test.DataPath); DataFileReader reader = new DataFileReader(); reader.LoadConfiguration(null, item); reader.LoadHistoryData(null, item); AggregateConfiguration configuration = new AggregateConfiguration(); configuration.PercentDataBad = 100; configuration.PercentDataGood = 100; configuration.TreatUncertainAsBad = test.TreatUncertainAsBad; configuration.UseSlopedExtrapolation = test.UseSlopedExtrapolation; configuration.UseServerCapabilitiesDefaults = false; DateTime startTime = DateTime.UtcNow; startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0, DateTimeKind.Utc); AggregateCalculator calculator = new AggregateCalculator( test.AggregateId, startTime.AddSeconds(0), startTime.AddSeconds(100), 5000, test.Stepped, configuration); StringBuilder buffer = new StringBuilder(); List<DataValue> values = new List<DataValue>(); foreach (DataRowView row in item.DataSet.Tables[0].DefaultView) { DataValue rawValue = (DataValue)row.Row[2]; if (!calculator.QueueRawValue(rawValue)) { Utils.Trace("Oops!"); continue; } DataValue processedValue = calculator.GetProcessedValue(false); if (processedValue != null) { values.Add(processedValue); } } for (DataValue processedValue = calculator.GetProcessedValue(true); processedValue != null; processedValue = calculator.GetProcessedValue(true)) { values.Add(processedValue); } for (int ii = 0; ii < values.Count && ii < expectedValues.Count; ii++) { if (values[ii].SourceTimestamp != expectedValues[ii].SourceTimestamp) { Utils.Trace("Wrong Status Timestamp"); continue; } if (values[ii].StatusCode != expectedValues[ii].StatusCode) { Utils.Trace("Wrong Status Code"); continue; } if (StatusCode.IsNotBad(values[ii].StatusCode)) { double value1 = Math.Round(Convert.ToDouble(values[ii].Value), 4); double value2 = Math.Round(Convert.ToDouble(expectedValues[ii].Value), 4); if (value1 != value2) { Utils.Trace("Wrong Value"); continue; } } } foreach (DataValue processedValue in values) { buffer.Append(processedValue.SourceTimestamp.ToString("HH:mm:ss")); buffer.Append(", "); buffer.Append(processedValue.WrappedValue); buffer.Append(", "); buffer.Append(new StatusCode(processedValue.StatusCode.CodeBits)); buffer.Append(", "); buffer.Append(processedValue.StatusCode.AggregateBits); buffer.Append("\r\n"); } // write to the file. using (StreamWriter writer = new StreamWriter(filePath)) { writer.Write(buffer.ToString()); } }
/// <summary> /// Creates items from embedded resources. /// </summary> private void CreateFolderFromResources(NodeState root, string folderName) { FolderState dataFolder = new FolderState(root); dataFolder.ReferenceTypeId = ReferenceTypeIds.Organizes; dataFolder.TypeDefinitionId = ObjectTypeIds.FolderType; dataFolder.NodeId = new NodeId(folderName, NamespaceIndex); dataFolder.BrowseName = new QualifiedName(folderName, NamespaceIndex); dataFolder.DisplayName = dataFolder.BrowseName.Name; dataFolder.WriteMask = AttributeWriteMask.None; dataFolder.UserWriteMask = AttributeWriteMask.None; dataFolder.EventNotifier = EventNotifiers.None; root.AddChild(dataFolder); AddPredefinedNode(SystemContext, root); foreach (string resourcePath in Assembly.GetExecutingAssembly().GetManifestResourceNames()) { if (!resourcePath.StartsWith("Quickstarts.HistoricalAccessServer.Data." + folderName)) { continue; } ArchiveItem item = new ArchiveItem(resourcePath, Assembly.GetExecutingAssembly(), resourcePath); ArchiveItemState node = new ArchiveItemState(SystemContext, item, NamespaceIndex); node.ReloadFromSource(SystemContext); dataFolder.AddReference(ReferenceTypeIds.Organizes, false, node.NodeId); node.AddReference(ReferenceTypeIds.Organizes, true, dataFolder.NodeId); AddPredefinedNode(SystemContext, node); } }
/// <summary> /// Loads the item configuaration. /// </summary> public bool LoadConfiguration(ISystemContext context, ArchiveItem item) { using (StreamReader reader = item.OpenArchive()) { while (!reader.EndOfStream) { string line = reader.ReadLine(); // check for end or error. if (line == null) { break; } // ignore blank lines. line = line.Trim(); if (String.IsNullOrEmpty(line)) { continue; } // ignore commented out lines. if (line.StartsWith("//")) { continue; } BuiltInType dataType = BuiltInType.String; int valueRank = ValueRanks.Scalar; int samplingInterval = 0; int simulationType = 0; int amplitude = 0; int period = 0; int archiving = 0; int stepped = 0; int useSlopedExtrapolation = 0; int treatUncertainAsBad = 0; int percentDataBad = 0; int percentDataGood = 0; // get data type. if (!ExtractField(1, ref line, out dataType)) { return(false); } // get value rank. if (!ExtractField(1, ref line, out valueRank)) { return(false); } // get sampling interval. if (!ExtractField(1, ref line, out samplingInterval)) { return(false); } // get simulation type. if (!ExtractField(1, ref line, out simulationType)) { return(false); } // get simulation amplitude. if (!ExtractField(1, ref line, out amplitude)) { return(false); } // get simulation period. if (!ExtractField(1, ref line, out period)) { return(false); } // get flag indicating whether new data is generated. if (!ExtractField(1, ref line, out archiving)) { return(false); } // get flag indicating whether stepped interpolation is used. if (!ExtractField(1, ref line, out stepped)) { return(false); } // get flag indicating whether sloped interpolation should be used. if (!ExtractField(1, ref line, out useSlopedExtrapolation)) { return(false); } // get flag indicating whether sloped interpolation should be used. if (!ExtractField(1, ref line, out treatUncertainAsBad)) { return(false); } // get the maximum permitted of bad data in an interval. if (!ExtractField(1, ref line, out percentDataBad)) { return(false); } // get the minimum amount of good data in an interval. if (!ExtractField(1, ref line, out percentDataGood)) { return(false); } // update the item. item.DataType = dataType; item.ValueRank = valueRank; item.SimulationType = simulationType; item.Amplitude = amplitude; item.Period = period; item.SamplingInterval = samplingInterval; item.Archiving = archiving != 0; item.Stepped = stepped != 0; item.AggregateConfiguration = new AggregateConfiguration(); item.AggregateConfiguration.UseServerCapabilitiesDefaults = false; item.AggregateConfiguration.UseSlopedExtrapolation = useSlopedExtrapolation != 0; item.AggregateConfiguration.TreatUncertainAsBad = treatUncertainAsBad != 0; item.AggregateConfiguration.PercentDataBad = (byte)percentDataBad; item.AggregateConfiguration.PercentDataGood = (byte)percentDataGood; break; } } return(true); }
/// <summary> /// Creates new data. /// </summary> public void CreateData(ArchiveItem item) { // get the data set to use. DataSet dataset = item.DataSet; if (dataset == null) { dataset = CreateDataSet(); } // generate one hour worth of data by default. DateTime startTime = DateTime.UtcNow.AddHours(-1); startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0, DateTimeKind.Utc); // check for existing data. if (dataset.Tables[0].Rows.Count > 0) { int index = dataset.Tables[0].DefaultView.Count; DateTime endTime = (DateTime)dataset.Tables[0].DefaultView[index - 1].Row[0]; endTime = startTime.AddMilliseconds(item.SamplingInterval); } DateTime currentTime = startTime; Opc.Ua.Test.DataGenerator generator = new Opc.Ua.Test.DataGenerator(null); while (currentTime < DateTime.UtcNow) { DataValue dataValue = new DataValue(); dataValue.SourceTimestamp = currentTime; dataValue.ServerTimestamp = currentTime.AddSeconds(generator.GetRandomByte()); dataValue.StatusCode = StatusCodes.Good; // generate random value. if (item.ValueRank < 0) { dataValue.Value = generator.GetRandom(item.DataType); } else { dataValue.Value = generator.GetRandomArray(item.DataType, false, 10, false); } // add record to table. DataRow row = dataset.Tables[0].NewRow(); row[0] = dataValue.SourceTimestamp; row[1] = dataValue.ServerTimestamp; row[2] = dataValue; row[3] = dataValue.WrappedValue.TypeInfo.BuiltInType; row[4] = dataValue.WrappedValue.TypeInfo.ValueRank; dataset.Tables[0].Rows.Add(row); // increment timestamp. currentTime = currentTime.AddMilliseconds(item.SamplingInterval); } dataset.AcceptChanges(); item.DataSet = dataset; }
/// <summary> /// Loads the item configuaration. /// </summary> public bool LoadConfiguration(ISystemContext context, ArchiveItem item) { using (StreamReader reader = item.OpenArchive()) { while (!reader.EndOfStream) { string line = reader.ReadLine(); // check for end or error. if (line == null) { break; } // ignore blank lines. line = line.Trim(); if (String.IsNullOrEmpty(line)) { continue; } // ignore commented out lines. if (line.StartsWith("//")) { continue; } BuiltInType dataType = BuiltInType.String; int valueRank = ValueRanks.Scalar; int samplingInterval = 0; int simulationType = 0; int amplitude = 0; int period = 0; int archiving = 0; int stepped = 0; int useSlopedExtrapolation = 0; int treatUncertainAsBad = 0; int percentDataBad = 0; int percentDataGood = 0; // get data type. if (!ExtractField(1, ref line, out dataType)) { return false; } // get value rank. if (!ExtractField(1, ref line, out valueRank)) { return false; } // get sampling interval. if (!ExtractField(1, ref line, out samplingInterval)) { return false; } // get simulation type. if (!ExtractField(1, ref line, out simulationType)) { return false; } // get simulation amplitude. if (!ExtractField(1, ref line, out amplitude)) { return false; } // get simulation period. if (!ExtractField(1, ref line, out period)) { return false; } // get flag indicating whether new data is generated. if (!ExtractField(1, ref line, out archiving)) { return false; } // get flag indicating whether stepped interpolation is used. if (!ExtractField(1, ref line, out stepped)) { return false; } // get flag indicating whether sloped interpolation should be used. if (!ExtractField(1, ref line, out useSlopedExtrapolation)) { return false; } // get flag indicating whether sloped interpolation should be used. if (!ExtractField(1, ref line, out treatUncertainAsBad)) { return false; } // get the maximum permitted of bad data in an interval. if (!ExtractField(1, ref line, out percentDataBad)) { return false; } // get the minimum amount of good data in an interval. if (!ExtractField(1, ref line, out percentDataGood)) { return false; } // update the item. item.DataType = dataType; item.ValueRank = valueRank; item.SimulationType = simulationType; item.Amplitude = amplitude; item.Period = period; item.SamplingInterval = samplingInterval; item.Archiving = archiving != 0; item.Stepped = stepped != 0; item.AggregateConfiguration = new AggregateConfiguration(); item.AggregateConfiguration.UseServerCapabilitiesDefaults = false; item.AggregateConfiguration.UseSlopedExtrapolation = useSlopedExtrapolation != 0; item.AggregateConfiguration.TreatUncertainAsBad = treatUncertainAsBad != 0; item.AggregateConfiguration.PercentDataBad = (byte)percentDataBad; item.AggregateConfiguration.PercentDataGood = (byte)percentDataGood; break; } } return true; }
/// <summary> /// Loads the history for the item. /// </summary> public void LoadHistoryData(ISystemContext context, ArchiveItem item) { // use the beginning of the current hour for the baseline. DateTime baseline = DateTime.UtcNow; baseline = new DateTime(baseline.Year, baseline.Month, baseline.Day, baseline.Hour, 0, 0, DateTimeKind.Utc); using (StreamReader reader = item.OpenArchive()) { // skip configuration line. reader.ReadLine(); item.DataSet = LoadData(context, baseline, reader); } // create a random dataset if nothing found in the archive, if (item.DataSet == null || item.DataSet.Tables[0].Rows.Count == 0) { CreateData(item); } // update the timestamp. item.LastLoadTime = DateTime.UtcNow; }
/// <summary> /// Creates new data. /// </summary> public void CreateData(ArchiveItem item) { // get the data set to use. DataSet dataset = item.DataSet; if (dataset == null) { dataset = CreateDataSet(); } // generate one hour worth of data by default. DateTime startTime = DateTime.UtcNow.AddHours(-1); startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0, DateTimeKind.Utc); // check for existing data. if (dataset.Tables[0].Rows.Count > 0) { int index = dataset.Tables[0].DefaultView.Count; DateTime endTime = (DateTime)dataset.Tables[0].DefaultView[index-1].Row[0]; endTime = startTime.AddMilliseconds(item.SamplingInterval); } DateTime currentTime = startTime; Opc.Ua.Test.DataGenerator generator = new Opc.Ua.Test.DataGenerator(null); while (currentTime < DateTime.UtcNow) { DataValue dataValue = new DataValue(); dataValue.SourceTimestamp = currentTime; dataValue.ServerTimestamp = currentTime.AddSeconds(generator.GetRandomByte()); dataValue.StatusCode = StatusCodes.Good; // generate random value. if (item.ValueRank < 0) { dataValue.Value = generator.GetRandom(item.DataType); } else { dataValue.Value = generator.GetRandomArray(item.DataType, false, 10, false); } // add record to table. DataRow row = dataset.Tables[0].NewRow(); row[0] = dataValue.SourceTimestamp; row[1] = dataValue.ServerTimestamp; row[2] = dataValue; row[3] = dataValue.WrappedValue.TypeInfo.BuiltInType; row[4] = dataValue.WrappedValue.TypeInfo.ValueRank; dataset.Tables[0].Rows.Add(row); // increment timestamp. currentTime = currentTime.AddMilliseconds(item.SamplingInterval); } dataset.AcceptChanges(); item.DataSet = dataset; }