private async Task RunQueryAggregateSeriesSample(TimeSeriesInsightsQueries queriesClient, TimeSeriesId tsId) { #region Snippet:TimeSeriesInsightsSampleQueryAggregateSeriesWithNumericVariable Console.WriteLine("\n\nQuery for the average temperature over the past 30 seconds, in 2-second time slots.\n"); var numericVariable = new NumericVariable( new TimeSeriesExpression("$event.Temperature"), new TimeSeriesExpression("avg($value)")); var requestOptions = new QueryAggregateSeriesRequestOptions(); requestOptions.InlineVariables["Temperature"] = numericVariable; requestOptions.ProjectedVariableNames.Add("Temperature"); QueryAnalyzer aggregateSeriesQuery = queriesClient.CreateAggregateSeriesQuery( tsId, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(30), null, requestOptions); await foreach (TimeSeriesPoint point in aggregateSeriesQuery.GetResultsAsync()) { double?averageTemperature = point.GetNullableDouble("Temperature"); if (averageTemperature != null) { Console.WriteLine($"{point.Timestamp} - Average temperature: {averageTemperature}."); } } #endregion Snippet:TimeSeriesInsightsSampleQueryAggregateSeriesWithNumericVariable #region Snippet:TimeSeriesInsightsSampleQueryAggregateSeriesWithAggregateVariable Console.WriteLine("\n\nCount the number of temperature events over the past 3 minutes, in 1-minute time slots.\n"); // Get the count of events in 60-second time slots over the past 3 minutes DateTimeOffset endTime = DateTime.UtcNow; DateTimeOffset startTime = endTime.AddMinutes(-3); var aggregateVariable = new AggregateVariable( new TimeSeriesExpression("count()")); var countVariableName = "Count"; var aggregateSeriesRequestOptions = new QueryAggregateSeriesRequestOptions(); aggregateSeriesRequestOptions.InlineVariables[countVariableName] = aggregateVariable; aggregateSeriesRequestOptions.ProjectedVariableNames.Add(countVariableName); QueryAnalyzer query = queriesClient.CreateAggregateSeriesQuery( tsId, startTime, endTime, TimeSpan.FromSeconds(60), aggregateSeriesRequestOptions); await foreach (TimeSeriesPoint point in query.GetResultsAsync()) { long?temperatureCount = (long?)point.GetValue(countVariableName); Console.WriteLine($"{point.Timestamp} - Temperature count: {temperatureCount}"); } #endregion Snippet:TimeSeriesInsightsSampleQueryAggregateSeriesWithAggregateVariable }
private async Task <string> createTimeSeriesTypeAsync(TimeSeriesInsightsClient client) { var timeSeriesTypes = new List <TimeSeriesType>(); var tsiTypeNamePrefix = "type"; var timeSeriesTypesName = Recording.GenerateAlphaNumericId(tsiTypeNamePrefix); string timeSeriesTypeId = Recording.GenerateId(); // Build aggregate variable var countExpression = new TimeSeriesExpression("count()"); var aggregateVariable = new AggregateVariable(countExpression); var variables = new Dictionary <string, TimeSeriesVariable>(); var variableNamePrefix = "aggregateVariable"; variables.Add(Recording.GenerateAlphaNumericId(variableNamePrefix), aggregateVariable); var type = new TimeSeriesType(timeSeriesTypesName, variables); type.Id = timeSeriesTypeId; timeSeriesTypes.Add(type); Response <TimeSeriesOperationError[]> createTypesResult = await client .CreateOrReplaceTimeSeriesTypesAsync(timeSeriesTypes) .ConfigureAwait(false); createTypesResult.Value.Should().OnlyContain((errorResult) => errorResult == null); return(timeSeriesTypeId); }
public async Task TimeSeriesInsightsTypes_Lifecycle() { // Arrange TimeSeriesInsightsClient client = GetClient(); var timeSeriesTypes = new List <TimeSeriesType>(); var tsiTypeNamePrefix = "type"; int numOfTypesCreated = 0; var timeSeriesTypesProperties = new Dictionary <string, string> { { Recording.GenerateAlphaNumericId(tsiTypeNamePrefix), Recording.GenerateId() }, { Recording.GenerateAlphaNumericId(tsiTypeNamePrefix), Recording.GenerateId() } }; // Build aggregate variable var countExpression = new TimeSeriesExpression("count()"); var aggregateVariable = new AggregateVariable(countExpression); var variables = new Dictionary <string, TimeSeriesVariable>(); var variableNamePrefix = "aggregateVariable"; variables.Add(Recording.GenerateAlphaNumericId(variableNamePrefix), aggregateVariable); foreach (var property in timeSeriesTypesProperties) { var type = new TimeSeriesType(property.Key, variables); type.Id = property.Value; timeSeriesTypes.Add(type); numOfTypesCreated++; } // Act and assert try { // Get all Time Series types in the environment AsyncPageable <TimeSeriesType> getAllTypesResponse = client.GetTimeSeriesTypesAsync(); await foreach (TimeSeriesType tsiType in getAllTypesResponse) { tsiType.Should().NotBeNull(); } // Create Time Series types Response <TimeSeriesOperationError[]> createTypesResult = await client .CreateOrReplaceTimeSeriesTypesAsync(timeSeriesTypes) .ConfigureAwait(false); // Assert that the result error array does not contain any object that is set createTypesResult.Value.Should().OnlyContain((errorResult) => errorResult == null); Response <TimeSeriesTypeOperationResult[]> getTypesByNamesResult; // This retry logic was added as the TSI types are not immediately available after creation await TestRetryHelper.RetryAsync <Response <TimeSeriesTypeOperationResult[]> >(async() => { // Get the created types by names getTypesByNamesResult = await client .GetTimeSeriesTypesByNamesAsync(timeSeriesTypesProperties.Keys) .ConfigureAwait(false); getTypesByNamesResult.Value.Should().OnlyContain((errorResult) => errorResult.Error == null); getTypesByNamesResult.Value.Length.Should().Be(timeSeriesTypes.Count); foreach (TimeSeriesTypeOperationResult typesResult in getTypesByNamesResult.Value) { typesResult.Error.Should().BeNull(); typesResult.TimeSeriesType.Should().NotBeNull(); typesResult.TimeSeriesType.Id.Should().NotBeNullOrEmpty(); typesResult.TimeSeriesType.Variables.Count.Should().Be(1); typesResult.TimeSeriesType.Variables.IsSameOrEqualTo(variables); } return(null); }, MaxNumberOfRetries, s_retryDelay); // Update variables with adding a new variable foreach (var type in timeSeriesTypes) { type.Description = "Description"; } Response <TimeSeriesOperationError[]> updateTypesResult = await client .CreateOrReplaceTimeSeriesTypesAsync(timeSeriesTypes) .ConfigureAwait(false); updateTypesResult.Value.Should().OnlyContain((errorResult) => errorResult == null); updateTypesResult.Value.Length.Should().Be(timeSeriesTypes.Count); // This retry logic was added as the TSI types are not immediately available after creation await TestRetryHelper.RetryAsync <Response <TimeSeriesTypeOperationResult[]> >(async() => { // Get type by Id Response <TimeSeriesTypeOperationResult[]> getTypeByIdResult = await client .GetTimeSeriesTypesByIdAsync(timeSeriesTypesProperties.Values) .ConfigureAwait(false); getTypeByIdResult.Value.Length.Should().Be(numOfTypesCreated); foreach (TimeSeriesTypeOperationResult typeOperationResult in getTypeByIdResult.Value) { typeOperationResult.TimeSeriesType.Should().NotBeNull(); typeOperationResult.Error.Should().BeNull(); typeOperationResult.TimeSeriesType.Name.Should().StartWith(tsiTypeNamePrefix); typeOperationResult.TimeSeriesType.Id.Should().NotBeNull(); } return(null); }, MaxNumberOfRetries, s_retryDelay); } finally { // clean up try { Response <TimeSeriesOperationError[]> deleteTypesResponse = await client .DeleteTimeSeriesTypesbyIdAsync(timeSeriesTypesProperties.Values) .ConfigureAwait(false); // Assert that the response array does not have any error object set deleteTypesResponse.Value.Should().OnlyContain((errorResult) => errorResult == null); } catch (Exception ex) { Console.WriteLine($"Test clean up failed: {ex.Message}"); throw; } } }
/// <summary> /// This sample demonstrates getting Time Series model settings, updating model settings and changing the default type Id for a model. /// </summary> public async Task RunSamplesAsync(TimeSeriesInsightsClient client) { PrintHeader("TIME SERIES INSIGHTS MODEL SETTINGS SAMPLE"); #region Snippet:TimeSeriesInsightsSampleGetModelSettings TimeSeriesInsightsModelSettings modelSettingsClient = client.GetModelSettingsClient(); TimeSeriesInsightsTypes typesClient = client.GetTypesClient(); Response <TimeSeriesModelSettings> getModelSettingsResponse = await modelSettingsClient.GetAsync(); Console.WriteLine($"Retrieved Time Series Insights model settings \nname : '{getModelSettingsResponse.Value.Name}', " + $"default type Id: {getModelSettingsResponse.Value.DefaultTypeId}'"); IReadOnlyList <TimeSeriesIdProperty> timeSeriesIdProperties = getModelSettingsResponse.Value.TimeSeriesIdProperties; foreach (TimeSeriesIdProperty property in timeSeriesIdProperties) { Console.WriteLine($"Time Series Id property name : '{property.Name}', type : '{property.PropertyType}'."); } #endregion Snippet:TimeSeriesInsightsSampleGetModelSettings // Store the default type Id so it can be used during clean up string defaultTypeId = getModelSettingsResponse.Value.DefaultTypeId; #region Snippet:TimeSeriesInsightsSampleUpdateModelSettingsName Response <TimeSeriesModelSettings> updateModelSettingsNameResponse = await modelSettingsClient.UpdateNameAsync("NewModelSettingsName"); Console.WriteLine($"Updated Time Series Insights model settings name: " + $"{updateModelSettingsNameResponse.Value.Name}"); #endregion Snippet:TimeSeriesInsightsSampleUpdateModelSettingsName // For every Time Series Insights environment, there is a default type that any newly created Time Series instance will be associated with. // You can change the default type for a TSI environment by creating a new type and calling the API to update the default type Id. // Create a Time Series type. var aggregateVariable = new AggregateVariable(new TimeSeriesExpression("count()")); var variables = new Dictionary <string, TimeSeriesVariable> { { "aggregateVariableName", aggregateVariable }, }; var type = new TimeSeriesType("tsiTypeName", variables); var timeSeriesTypes = new List <TimeSeriesType> { type }; string tsiTypeId = null; Response <TimeSeriesTypeOperationResult[]> createTsiTypeResponse = await typesClient .CreateOrReplaceAsync(timeSeriesTypes); // Ensure no error was reported as part of the response if (createTsiTypeResponse.Value[0].Error == null) { // Store the Time Series type id to use it for updating default type in model settings tsiTypeId = createTsiTypeResponse.Value[0].TimeSeriesType.Id; #region Snippet:TimeSeriesInsightsSampleUpdateModelSettingsDefaultType Response <TimeSeriesModelSettings> updateDefaultTypeIdResponse = await modelSettingsClient .UpdateDefaultTypeIdAsync(tsiTypeId); Console.WriteLine($"Updated Time Series Insights model settings default type Id: " + $"{updateDefaultTypeIdResponse.Value.Name}"); #endregion Snippet:TimeSeriesInsightsSampleUpdateModelSettingsDefaultType } // Clean up try { // Revert back to the original default type Id await modelSettingsClient .UpdateDefaultTypeIdAsync(defaultTypeId); // Delete the type created if (tsiTypeId != null) { await typesClient .DeleteByIdAsync(new List <string> { tsiTypeId }); } } catch (Exception ex) { Console.WriteLine($"Failed at one of the clean up steps: {ex.Message}"); } }
public async Task TimeSeriesInsightsQuery_AggregateSeriesWithAggregateVariable() { // Arrange TimeSeriesInsightsClient tsiClient = GetClient(); DeviceClient deviceClient = await GetDeviceClient().ConfigureAwait(false); // Figure out what the Time Series Id is composed of TimeSeriesModelSettings modelSettings = await tsiClient.ModelSettings.GetAsync().ConfigureAwait(false); // Create a Time Series Id where the number of keys that make up the Time Series Id is fetched from Model Settings TimeSeriesId tsiId = await GetUniqueTimeSeriesInstanceIdAsync(tsiClient, modelSettings.TimeSeriesIdProperties.Count) .ConfigureAwait(false); try { // Send some events to the IoT hub with with a second between each event await QueryTestsHelper.SendEventsToHubAsync( deviceClient, tsiId, modelSettings.TimeSeriesIdProperties.ToArray(), 30) .ConfigureAwait(false); // Query for temperature events with two calculateions. First with the temperature value as is, and the second // with the temperature value multiplied by 2. DateTimeOffset now = Recording.UtcNow; DateTimeOffset endTime = now.AddMinutes(10); DateTimeOffset startTime = now.AddMinutes(-10); var aggregateVariable = new AggregateVariable( new TimeSeriesExpression("count()")); var queryAggregateSeriesRequestOptions = new QueryAggregateSeriesRequestOptions(); queryAggregateSeriesRequestOptions.InlineVariables["Count"] = aggregateVariable; queryAggregateSeriesRequestOptions.ProjectedVariables.Add("Count"); // This retry logic was added as the TSI instance are not immediately available after creation await TestRetryHelper.RetryAsync <AsyncPageable <QueryResultPage> >(async() => { QueryAnalyzer queryAggregateSeriesPages = tsiClient.Queries.CreateAggregateSeriesQueryAnalyzer( tsiId, startTime, endTime, TimeSpan.FromSeconds(5), queryAggregateSeriesRequestOptions); long?totalCount = 0; await foreach (TimeSeriesPoint point in queryAggregateSeriesPages.GetResultsAsync()) { var currentCount = (long?)point.GetValue("Count"); totalCount += currentCount; } totalCount.Should().Be(30); return(null); }, MaxNumberOfRetries, s_retryDelay); } finally { deviceClient?.Dispose(); } }
/// <summary> /// This sample demonstrates usage of Time Series Insights types APIs. /// </summary> public async Task RunSamplesAsync(TimeSeriesInsightsClient client) { // For the purpose of keeping code snippets readable to the user, hardcoded string literals are used in place of assigned variables, eg Ids. // Despite not being a good code practice, this prevents code snippets from being out of context for the user when making API calls that accept Ids as parameters. PrintHeader("TIME SERIES INSIGHTS TYPES SAMPLE"); #region Snippet:TimeSeriesInsightsSampleCreateType // Create a type with an aggregate variable var timeSeriesTypes = new List <TimeSeriesType>(); var countExpression = new TimeSeriesExpression("count()"); var aggregateVariable = new AggregateVariable(countExpression); var variables = new Dictionary <string, TimeSeriesVariable>(); variables.Add("aggregateVariable", aggregateVariable); timeSeriesTypes.Add(new TimeSeriesType("Type1", variables) { Id = "Type1Id" }); timeSeriesTypes.Add(new TimeSeriesType("Type2", variables) { Id = "Type2Id" }); Response <TimeSeriesTypeOperationResult[]> createTypesResult = await client .Types .CreateOrReplaceAsync(timeSeriesTypes); // The response of calling the API contains a list of error objects corresponding by position to the input parameter array in the request. // If the error object is set to null, this means the operation was a success. for (int i = 0; i < createTypesResult.Value.Length; i++) { if (createTypesResult.Value[i].Error == null) { Console.WriteLine($"Created Time Series type successfully."); } else { Console.WriteLine($"Failed to create a Time Series Insights type: {createTypesResult.Value[i].Error.Message}."); } } #endregion Snippet:TimeSeriesInsightsSampleCreateType #region Snippet:TimeSeriesInsightsSampleGetTypeById // Code snippet below shows getting a default Type using Id // The default type Id can be obtained programmatically by using the ModelSettings client. TimeSeriesModelSettings modelSettings = await client.ModelSettings.GetAsync(); Response <TimeSeriesTypeOperationResult[]> getTypeByIdResults = await client .Types .GetByIdAsync(new string[] { modelSettings.DefaultTypeId }); // The response of calling the API contains a list of type or error objects corresponding by position to the input parameter array in the request. // If the error object is set to null, this means the operation was a success. for (int i = 0; i < getTypeByIdResults.Value.Length; i++) { if (getTypeByIdResults.Value[i].Error == null) { Console.WriteLine($"Retrieved Time Series type with Id: '{getTypeByIdResults.Value[i].TimeSeriesType.Id}'."); } else { Console.WriteLine($"Failed to retrieve a Time Series type due to '{getTypeByIdResults.Value[i].Error.Message}'."); } } #endregion Snippet:TimeSeriesInsightsSampleGetTypeById #region Snippet:TimeSeriesInsightsSampleReplaceType // Update variables with adding a new variable foreach (TimeSeriesType type in timeSeriesTypes) { type.Description = "Description"; } Response <TimeSeriesTypeOperationResult[]> updateTypesResult = await client .Types .CreateOrReplaceAsync(timeSeriesTypes); // The response of calling the API contains a list of error objects corresponding by position to the input parameter array in the request. // If the error object is set to null, this means the operation was a success. for (int i = 0; i < updateTypesResult.Value.Length; i++) { if (updateTypesResult.Value[i].Error == null) { Console.WriteLine($"Updated Time Series type successfully."); } else { Console.WriteLine($"Failed to update a Time Series Insights type due to: {updateTypesResult.Value[i].Error.Message}."); } } #endregion Snippet:TimeSeriesInsightsSampleReplaceType #region Snippet:TimeSeriesInsightsSampleGetAllTypes // Get all Time Series types in the environment AsyncPageable <TimeSeriesType> getAllTypesResponse = client.Types.GetTypesAsync(); await foreach (TimeSeriesType tsiType in getAllTypesResponse) { Console.WriteLine($"Retrieved Time Series Insights type with Id: '{tsiType?.Id}' and Name: '{tsiType?.Name}'"); } #endregion Snippet:TimeSeriesInsightsSampleGetAllTypes // Clean up try { #region Snippet:TimeSeriesInsightsSampleDeleteTypeById // Delete Time Series types with Ids var typesIdsToDelete = new List <string> { "Type1Id", " Type2Id" }; Response <TimeSeriesOperationError[]> deleteTypesResponse = await client .Types .DeleteByIdAsync(typesIdsToDelete); // The response of calling the API contains a list of error objects corresponding by position to the input parameter // array in the request. If the error object is set to null, this means the operation was a success. foreach (var result in deleteTypesResponse.Value) { if (result != null) { Console.WriteLine($"Failed to delete a Time Series Insights type: {result.Message}."); } else { Console.WriteLine($"Deleted a Time Series Insights type successfully."); } } #endregion Snippet:TimeSeriesInsightsSampleDeleteTypeById } catch (Exception ex) { Console.WriteLine($"Failed to delete Time Series Insights type: {ex.Message}"); } }