private static async Task MainAsync() { string accountId = ConfigurationManager.AppSettings["accountId"]; string namespaceId = ConfigurationManager.AppSettings["namespaceId"]; string address = ConfigurationManager.AppSettings["address"]; string resource = ConfigurationManager.AppSettings["resource"]; string clientId = ConfigurationManager.AppSettings["clientId"]; string clientSecret = ConfigurationManager.AppSettings["clientSecret"]; string piServerName = ConfigurationManager.AppSettings["PIDataArchive"]; var qiService = new QiService(new Uri(address), new QiSecurityHandler(resource, accountId, clientId, clientSecret)); var metadataService = qiService.GetMetadataService(accountId, namespaceId); var dataService = qiService.GetDataService(accountId, namespaceId); var piServer = new PIServers()[piServerName]; piServer.Connect(); PIPointQuery nameFilter = new PIPointQuery { AttributeName = PICommonPointAttributes.Tag, AttributeValue = _options.TagMask, Operator = OSIsoft.AF.Search.AFSearchOperator.Equal }; IEnumerable <string> attributesToRetrieve = new[] { PICommonPointAttributes.Descriptor, PICommonPointAttributes.EngineeringUnits, PICommonPointAttributes.PointSource }; var piPoints = (await PIPoint.FindPIPointsAsync(piServer, new[] { nameFilter }, attributesToRetrieve)).ToList(); if (!piPoints.Any()) { Console.WriteLine($"No points found matching the tagMask query!"); return; } Console.WriteLine($"Found {piPoints.Count} points matching mask: {_options.TagMask}"); //create types await PIQiTypes.CreateOrUpdateTypesInOcsAsync(metadataService); //delete existing streams if requested if (_options.Mode == CommandLineOptions.DataWriteModes.clearExistingData) { Parallel.ForEach(piPoints, piPoint => DeleteStreamBasedOnPIPointAsync(piPoint, metadataService).Wait()); } Parallel.ForEach(piPoints, piPoint => CreateStreamBasedOnPIPointAsync(piPoint, attributesToRetrieve, metadataService).Wait()); Console.WriteLine($"Created or updated {piPoints.Count()} streams."); //for each PIPoint, get the data of interest and write it to OCS Parallel.ForEach(piPoints, piPoint => { //Indices must be unique in OCS so we get rid of duplicate values for a given timestamp var timeRange = new AFTimeRange(_options.StartTime, _options.EndTime); var afValues = piPoint.RecordedValues(timeRange, AFBoundaryType.Inside, null, true) .GroupBy(value => value.Timestamp) .Select(valuesAtTimestamp => valuesAtTimestamp.Last()) //last event for particular timestamp .Where(val => val.IsGood) //System Digital States (e.g. Shutdown, IO Timeout, etc...) are ignored .ToList(); WriteDataToOcsAsync(piPoint, afValues, dataService).Wait(); }); }