public static async Task Main(string[] args) { var adtInstanceUrl = "https://ADT_INSTANCE_HOST_NAME"; var credential = new DefaultAzureCredential(); var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential); //retrieve the factory twin - this query will take a moment longer due to the cold start var factoryId = "FA44212"; var factory = client.GetDigitalTwin <BasicDigitalTwin>(factoryId); Console.WriteLine($"Factory {factory.Value.Id} retrieved."); foreach (KeyValuePair <string, object> prop in factory.Value.Contents) { Console.WriteLine($"Factory {factory.Value.Id} has Property: {prop.Key} with value {prop.Value.ToString()}"); } //output factory property metadata, indicating the last time the property was updated foreach (var md in factory.Value.Metadata.PropertyMetadata) { Console.WriteLine($"Factory {factory.Value.Id} Property: {md.Key} was last updated {md.Value.LastUpdatedOn}"); } //retrieve factory relationships IAsyncEnumerable <BasicRelationship> relationships = client.GetRelationshipsAsync <BasicRelationship>(factoryId); await foreach (BasicRelationship relationship in relationships) { Console.WriteLine($"Factory {factory.Value.Id} has relationship '{relationship.Name}' with {relationship.TargetId}"); } //retrieve only the Efficiency property value for the factory using a projection var projectionQuery1 = $"SELECT Factory.Efficiency FROM DIGITALTWINS Factory WHERE Factory.$dtId='{factoryId}'"; IAsyncEnumerable <JsonElement> response = client.QueryAsync <JsonElement>(projectionQuery1); await foreach (JsonElement ret in response) { Console.WriteLine($"{factoryId} Efficiency is at {ret.GetProperty("Efficiency")}"); } //retrieve factories with Efficiency equal to or over 90 var queryByPropertyValue = $"SELECT Factory FROM DIGITALTWINS Factory WHERE Factory.Efficiency >= 90"; IAsyncEnumerable <BasicDigitalTwin> response2 = client.QueryAsync <IDictionary <string, BasicDigitalTwin> >(queryByPropertyValue).Select(_ => _["Factory"]); await foreach (BasicDigitalTwin ret in response2) { Console.WriteLine($"Factory {ret.Id} has an Efficiency over 90."); } }
async public void QueryWithLoopAsync(DigitalTwinsClient client) { // ------------------ RUN QUERY & LOOP THROUGH PAGEABLE RESULTS WITH TRY/CATCH (Full sample) --------------------- // <FullQuerySample> AsyncPageable <BasicDigitalTwin> result = client.QueryAsync <BasicDigitalTwin>("Select * From DigitalTwins"); try { await foreach (BasicDigitalTwin twin in result) { // You can include your own logic to print the result // The logic below prints the twin's ID and contents Console.WriteLine($"Twin ID: {twin.Id} \nTwin data"); foreach (KeyValuePair <string, object> kvp in twin.Contents) { Console.WriteLine($"{kvp.Key} {kvp.Value}"); } } } catch (RequestFailedException ex) { Console.WriteLine($"Error {ex.Status}, {ex.ErrorCode}, {ex.Message}"); throw; } // </FullQuerySample> }
public static async Task <IEnumerable <double> > GetAllSensorValuesInRoomAsync(DigitalTwinsClient client, string roomdtid, string sensormodelid, ILogger log) { var query = "SELECT Sensor " + "FROM DIGITALTWINS Room " + "JOIN Sensor RELATED Room.hasCapability " + $"WHERE IS_OF_MODEL(Sensor, '{sensormodelid}') AND Room.$dtId = '{roomdtid}' AND IS_PRIMITIVE(Sensor.Value)"; try { List <double> values = new List <double>(); AsyncPageable <BasicDigitalTwin> twins = client.QueryAsync <BasicDigitalTwin>(query); await foreach (BasicDigitalTwin twin in twins) { var val = (JObject)JsonConvert.DeserializeObject(twin.Contents["Sensor"].ToString()); values.Add(double.Parse(val["Value"].ToString())); } return(values); } catch (RequestFailedException exc) { log.LogError($"*** Error in retrieving parent:{exc.Status}/{exc.Message}"); throw exc; } }
public static async Task <string> FindParentByQuery(DigitalTwinsClient client, string childId, ILogger log) { string query = $"SELECT Parent " + $"FROM digitaltwins Parent " + $"JOIN Child RELATED Parent.contains " + $"WHERE Child.$dtId = '" + childId + "'"; log.LogInformation($"Query: {query}"); try { AsyncPageable <string> res = client.QueryAsync(query); await foreach (string s in res) { JObject parentTwin = (JObject)JsonConvert.DeserializeObject(s); return((string)parentTwin["Parent"]["$dtId"]); } log.LogInformation($"*** No parent found"); } catch (RequestFailedException exc) { log.LogInformation($"*** Error in retrieving parent:{exc.Status}/{exc.Message}"); } return(null); }
private static async Task <List <BasicDigitalTwin> > Query(string query) { try { AsyncPageable <BasicDigitalTwin> queryResult = client.QueryAsync <BasicDigitalTwin>(query); var resultlist = new List <BasicDigitalTwin>(); await foreach (BasicDigitalTwin item in queryResult) { resultlist.Add(item); } return(resultlist); } catch (RequestFailedException e) { log.LogInformation($"RequestFailedException error {e.Status}: {e.Message}"); return(null); } catch (Exception ex) { log.LogInformation($"Exception error: {ex}"); return(null); } }
async public void Run(DigitalTwinsClient client) { AsyncPageable <BasicDigitalTwin> asyncPageableResponseWithCharge = client.QueryAsync <BasicDigitalTwin>("SELECT * FROM digitaltwins"); int pageNum = 0; // The "await" keyword here is required, as a call is made when fetching a new page. await foreach (Page <BasicDigitalTwin> page in asyncPageableResponseWithCharge.AsPages()) { Console.WriteLine($"Page {++pageNum} results:"); // Extract the query-charge header from the page if (QueryChargeHelper.TryGetQueryCharge(page, out float queryCharge)) { Console.WriteLine($"Query charge was: {queryCharge}"); } // Iterate over the twin instances. // The "await" keyword is not required here, as the paged response is local. foreach (BasicDigitalTwin twin in page.Values) { Console.WriteLine($"Found digital twin '{twin.Id}'"); } } }
public async Task DeleteAllTwinsAsync() { Console.WriteLine($"\nDeleting all twins"); Console.WriteLine($"Step 1: Find all twins", ConsoleColor.DarkYellow); List <string> twinlist = new List <string>(); try { AsyncPageable <string> qresult = client.QueryAsync("SELECT * FROM DIGITALTWINS"); await foreach (string item in qresult) { JsonDocument document = JsonDocument.Parse(item); if (document.RootElement.TryGetProperty("$dtId", out JsonElement eDtdl)) { try { string twinId = eDtdl.GetString(); twinlist.Add(twinId); } catch (Exception e) { Console.WriteLine("No DTDL property in query result"); } } else { Console.WriteLine($"Error: Can't find twin id in query result:\n {item}"); } } } catch (Exception ex) { Console.WriteLine($"Error in query execution: {ex.Message}"); } Console.WriteLine($"Step 2: Find and remove relationships for each twin...", ConsoleColor.DarkYellow); foreach (string twinId in twinlist) { // Remove any relationships for the twin await FindAndDeleteOutgoingRelationshipsAsync(twinId).ConfigureAwait(false); await FindAndDeleteIncomingRelationshipsAsync(twinId).ConfigureAwait(false); } Console.WriteLine($"Step 3: Delete all twins", ConsoleColor.DarkYellow); foreach (string twinId in twinlist) { try { await client.DeleteDigitalTwinAsync(twinId).ConfigureAwait(false); Console.WriteLine($"Deleted twin {twinId}"); } catch (RequestFailedException ex) { Console.WriteLine($"*** Error {ex.Status}/{ex.ErrorCode} deleting twin {twinId} due to {ex.Message}"); } } }
async public void QueryBasicAsync(DigitalTwinsClient client) { // ------------------ RUN QUERY (Basic) --------------------- // <RunQuery> // Run a query for all twins string query = "SELECT * FROM DIGITALTWINS"; AsyncPageable <BasicDigitalTwin> result = client.QueryAsync <BasicDigitalTwin>(query); // </RunQuery> }
public async Task Query_GetTwinAliasing() { DigitalTwinsClient client = GetClient(); string floorModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.FloorModelIdPrefix).ConfigureAwait(false); string roomModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomModelIdPrefix).ConfigureAwait(false); try { // arrange // Create room model string roomModel = TestAssetsHelper.GetRoomModelPayload(roomModelId, floorModelId); await CreateAndListModelsAsync(client, new List <string> { roomModel }).ConfigureAwait(false); // Create a room twin, with property "IsOccupied": true string roomTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomTwinIdPrefix).ConfigureAwait(false); BasicDigitalTwin roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); await client.CreateOrReplaceDigitalTwinAsync(roomTwinId, roomTwin).ConfigureAwait(false); await WaitIfLiveAsync(TimeSpan.FromSeconds(10)); // Use aliasing in the query to test deserialization when each digital twin in the response will be wrapped by the alias name. string queryString = $"SELECT D FROM DIGITALTWINS D"; // act AsyncPageable <AliasedBasicDigitalTwin> asyncPageableResponse = client.QueryAsync <AliasedBasicDigitalTwin>(queryString); await foreach (AliasedBasicDigitalTwin twin in asyncPageableResponse) { twin.Twin.Id.Should().NotBeNull(); } } catch (Exception ex) { Assert.Fail($"Failure in executing a step in the test case: {ex.Message}."); } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomModelId)) { await client.DeleteModelAsync(roomModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
public async Task Query_ValidQuery_Success() { DigitalTwinsClient client = GetClient(); string floorModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.FloorModelIdPrefix).ConfigureAwait(false); string roomModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomModelIdPrefix).ConfigureAwait(false); try { // arrange // Create room model string roomModel = TestAssetsHelper.GetRoomModelPayload(roomModelId, floorModelId); await client.CreateModelsAsync(new List <string> { roomModel }).ConfigureAwait(false); // Create a room twin, with property "IsOccupied": true string roomTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomTwinIdPrefix).ConfigureAwait(false); string roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); await client.CreateDigitalTwinAsync(roomTwinId, roomTwin).ConfigureAwait(false); string queryString = "SELECT * FROM digitaltwins where IsOccupied = true"; // act AsyncPageable <string> asyncPageableResponse = client.QueryAsync(queryString); // assert await foreach (string response in asyncPageableResponse) { JsonElement jsonElement = JsonSerializer.Deserialize <JsonElement>(response); JsonElement isOccupied = jsonElement.GetProperty("IsOccupied"); isOccupied.GetRawText().Should().Be("true"); } } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomModelId)) { await client.DeleteModelAsync(roomModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
public async Task <IEnumerable <Item> > All() { var result = client.QueryAsync <BasicDigitalTwin>("SELECT * FROM digitaltwins"); var items = new List <Item>(); await foreach (BasicDigitalTwin twin in result) { items.Add(new Item(twin.Id, twin.Metadata.ModelId)); } return(items); }
public static async Task <string> GetTwinId(DigitalTwinsClient client, string regId, ILogger log) { string query = $"SELECT * FROM DigitalTwins T WHERE T.HubRegistrationId = '{regId}'"; AsyncPageable <string> twins = client.QueryAsync(query); await foreach (string twinJson in twins) { JObject twin = (JObject)JsonConvert.DeserializeObject(twinJson); string dtId = (string)twin["$dtId"]; log.LogInformation($"Twin '{dtId}' found in DT"); return(dtId); } return(null); }
/// <summary> /// Queries for all digital twins using <see cref="DigitalTwinsClient.QueryAsync{T}(string, CancellationToken)"/>. /// </summary> /// <param name="cancellationToken">The token used to signal cancellation request.</param> public override async Task RunAsync(CancellationToken cancellationToken) { AsyncPageable <BasicDigitalTwin> result = _digitalTwinsClient .QueryAsync <BasicDigitalTwin>($"SELECT * FROM DIGITALTWINS WHERE TestId = '{_testId}'", cancellationToken); long resultCount = 0; await foreach (BasicDigitalTwin a in result) { resultCount++; } #if DEBUG resultCount.Should().Be(_size); #endif }
public static async Task <string> FindOrCreateTwinAsync(string dtmi, string regId, ILogger log) { // Create Digital Twins client var cred = new ManagedIdentityCredential(adtAppId); var client = new DigitalTwinsClient( new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(singletonHttpClientInstance) }); // Find existing twin with registration ID string query = $"SELECT * FROM DigitalTwins T WHERE $dtId = '{regId}' AND IS_OF_MODEL('{dtmi}')"; AsyncPageable <BasicDigitalTwin> twins = client.QueryAsync(query); string dtId; await foreach (BasicDigitalTwin digitalTwin in twins) { dtId = digitalTwin.Id; log.LogInformation($"Twin '{dtId}' with Registration ID '{regId}' found in DT"); break; } if (String.IsNullOrWhiteSpace(dtId)) { // Not found, so create new twin log.LogInformation($"Twin ID not found - setting DT ID to regID"); dtId = regId; // use the Registration ID as the DT ID // Initialize the twin properties var digitalTwin = new BasicDigitalTwin { Metadata = { ModelId = dtmi }, Contents = { { "Temperature", 0.0 }, }, }; await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(dtId, digitalTwin); log.LogInformation($"Twin '{dtId}' created in DT"); } return(dtId); }
public static async Task <string> FindOrCreateTwin(string dtmi, string regId, ILogger log) { // Create Digital Twins client var cred = new ManagedIdentityCredential(adtAppId); var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); // Find existing twin with registration ID string dtId; string query = $"SELECT * FROM DigitalTwins T WHERE $dtId = '{regId}' AND IS_OF_MODEL('{dtmi}')"; AsyncPageable <string> twins = client.QueryAsync(query); await foreach (string twinJson in twins) { // Get DT ID from the Twin JObject twin = (JObject)JsonConvert.DeserializeObject(twinJson); dtId = (string)twin["$dtId"]; log.LogInformation($"Twin '{dtId}' with Registration ID '{regId}' found in DT"); return(dtId); } // Not found, so create new twin log.LogInformation($"Twin ID not found, setting DT ID to regID"); dtId = regId; // use the Registration ID as the DT ID // Define the model type for the twin to be created Dictionary <string, object> meta = new Dictionary <string, object>() { { "$model", dtmi } }; // Initialize the twin properties Dictionary <string, object> twinProps = new Dictionary <string, object>() { { "$metadata", meta } }; twinProps.Add("Temperature", 0.0); await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(dtId, twinProps); log.LogInformation($"Twin '{dtId}' created in DT"); return(dtId); }
public static async Task <string> FindOrCreateTwin(string dtmi, string regId, ILogger log) { // Create Digital Twin client var cred = new ManagedIdentityCredential("https://digitaltwins.azure.net"); var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); // Find existing twin with registration ID string dtId; string query = $"SELECT * FROM DigitalTwins T WHERE T.HubRegistrationId = '{regId}' AND IS_OF_MODEL('{dtmi}')"; AsyncPageable <string> twins = client.QueryAsync(query); await foreach (string twinJson in twins) { // Get DT ID from the Twin JObject twin = (JObject)JsonConvert.DeserializeObject(twinJson); dtId = (string)twin["$dtId"]; log.LogInformation($"Twin '{dtId}' with Registration ID '{regId}' found in DT"); return(dtId); } // Not found, so create new twin dtId = regId; // use the Registration ID as the DT ID // Define the model type for the twin to be created Dictionary <string, object> meta = new Dictionary <string, object>() { { "$model", dtmi } }; // Initialize the twin properties Dictionary <string, object> twinProps = new Dictionary <string, object>() { { "$metadata", meta }, { "HubRegistrationId", regId } }; await client.CreateDigitalTwinAsync(dtId, System.Text.Json.JsonSerializer.Serialize <Dictionary <string, object> >(twinProps)); log.LogInformation($"Twin '{dtId}' created in DT"); return(dtId); }
public static async Task ReadProperty(DigitalTwinsClient client) { string dtID; string prop; Console.Write("Digital twin ID: "); dtID = Console.ReadLine(); Console.Write("Property name: "); prop = Console.ReadLine(); string q = string.Format("SELECT v.{0}, v.$metadata.{0}.lastUpdateTime FROM DIGITALTWINS v WHERE v.$dtId = '{1}' AND IS_PRIMITIVE(v.{0}) and IS_PRIMITIVE(v.$metadata.{0}.lastUpdateTime)", prop, dtID); Console.WriteLine("Query: {0}\n\r", q); AsyncPageable <string> result = client.QueryAsync(q); await foreach (string s in result) { Console.WriteLine(s); } }
private static async Task <DtIds> fetchDtIds(string query) { DtIds dtIds = new DtIds(); try { Azure.AsyncPageable <string> result = client.QueryAsync(query); IAsyncEnumerator <Azure.Page <string> > enumerator = result.AsPages().GetAsyncEnumerator(); while (await enumerator.MoveNextAsync()) { IReadOnlyList <string> values = enumerator.Current.Values; if (values.Count > 0) { JObject nodeData = JObject.Parse(values[0]); dtIds.sensor = (string)nodeData["$dtId"]; dtIds.turbineObserved = (string)nodeData["observes"]; } else { throw new Exception("Node not found!"); } } } catch {} return(dtIds); }
public static async Task <string> FindParentByQueryAsync(DigitalTwinsClient client, string childId, ILogger log) { string query = "SELECT Parent " + "FROM digitaltwins Parent " + "JOIN Child RELATED Parent.contains " + $"WHERE Child.$dtId = '{childId}'"; log.LogInformation($"Query: {query}"); try { AsyncPageable <BasicDigitalTwin> twins = client.QueryAsync <BasicDigitalTwin>(query); await foreach (BasicDigitalTwin twin in twins) { return(twin.Id); } log.LogWarning($"*** No parent found"); } catch (RequestFailedException exc) { log.LogError($"*** Error in retrieving parent:{exc.Status}/{exc.Message}"); } return(null); }
private async Task <List <string> > Query(string query) { try { AsyncPageable <string> qresult = client.QueryAsync(query); List <string> reslist = new List <string>(); await foreach (string item in qresult) { reslist.Add(item); } Print(reslist); return(reslist); } catch (RequestFailedException e) { Log.Error($"Error {e.Status}: {e.Message}"); return(null); } catch (Exception ex) { Log.Error($"Error: {ex}"); return(null); } }
public async Task QueryTwinsAsync() { PrintHeader("QUERY DIGITAL TWINS"); try { Console.WriteLine("Making a twin query and iterating over the results."); #region Snippet:DigitalTwinsSampleQueryTwins // This code snippet demonstrates the simplest way to iterate over the digital twin results, where paging // happens under the covers. AsyncPageable <string> asyncPageableResponse = client.QueryAsync("SELECT * FROM digitaltwins"); // Iterate over the twin instances in the pageable response. // The "await" keyword here is required because new pages will be fetched when necessary, // which involves a request to the service. await foreach (string response in asyncPageableResponse) { BasicDigitalTwin twin = JsonSerializer.Deserialize <BasicDigitalTwin>(response); Console.WriteLine($"Found digital twin: {twin.Id}"); } #endregion Snippet:DigitalTwinsSampleQueryTwins Console.WriteLine("Making a twin query, with query-charge header extraction."); #region Snippet:DigitalTwinsSampleQueryTwinsWithQueryCharge // This code snippet demonstrates how you could extract the query charges incurred when calling // the query API. It iterates over the response pages first to access to the query-charge header, // and then the digital twin results within each page. AsyncPageable <string> asyncPageableResponseWithCharge = client.QueryAsync("SELECT * FROM digitaltwins"); int pageNum = 0; // The "await" keyword here is required as a call is made when fetching a new page. await foreach (Page <string> page in asyncPageableResponseWithCharge.AsPages()) { Console.WriteLine($"Page {++pageNum} results:"); // Extract the query-charge header from the page if (QueryChargeHelper.TryGetQueryCharge(page, out float queryCharge)) { Console.WriteLine($"Query charge was: {queryCharge}"); } // Iterate over the twin instances. // The "await" keyword is not required here as the paged response is local. foreach (string response in page.Values) { BasicDigitalTwin twin = JsonSerializer.Deserialize <BasicDigitalTwin>(response); Console.WriteLine($"Found digital twin: {twin.Id}"); } } #endregion Snippet:DigitalTwinsSampleQueryTwinsWithQueryCharge } catch (Exception ex) { FatalError($"Could not query digital twins due to {ex}"); } }
public async Task Query_PaginationWorks() { DigitalTwinsClient client = GetClient(); int pageSize = 5; string floorModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.FloorModelIdPrefix).ConfigureAwait(false); string roomModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomModelIdPrefix).ConfigureAwait(false); try { // Create room model string roomModel = TestAssetsHelper.GetRoomModelPayload(roomModelId, floorModelId); await client.CreateModelsAsync(new List <string> { roomModel }).ConfigureAwait(false); // Create a room twin, with property "IsOccupied": true string roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); for (int i = 0; i < pageSize + 1; i++) { string roomTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomTwinIdPrefix).ConfigureAwait(false); await client.CreateDigitalTwinAsync(roomTwinId, roomTwin).ConfigureAwait(false); } string queryString = "SELECT * FROM digitaltwins"; // act var options = new QueryOptions(); options.MaxItemsPerPage = pageSize; AsyncPageable <string> asyncPageableResponse = client.QueryAsync(queryString, options); // assert // Test that page size hint works, and that all returned pages either have the page size hint amount of // elements, or have no continuation token (signaling that it is the last page) int pageCount = 0; await foreach (Page <string> page in asyncPageableResponse.AsPages()) { pageCount++; if (page.ContinuationToken != null) { page.Values.Count.Should().Be(pageSize, "Unexpected page size for a non-terminal page"); } } pageCount.Should().BeGreaterThan(1, "Expected more than one page of query results"); } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomModelId)) { await client.DeleteModelAsync(roomModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
public async Task Query_ValidQuery_Success() { DigitalTwinsClient client = GetClient(); string floorModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.FloorModelIdPrefix).ConfigureAwait(false); string roomModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomModelIdPrefix).ConfigureAwait(false); try { // arrange // Create room model string roomModel = TestAssetsHelper.GetRoomModelPayload(roomModelId, floorModelId); await CreateAndListModelsAsync(client, new List <string> { roomModel }).ConfigureAwait(false); // Create a room twin, with property "IsOccupied": true string roomTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomTwinIdPrefix).ConfigureAwait(false); BasicDigitalTwin roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); await client.CreateOrReplaceDigitalTwinAsync(roomTwinId, roomTwin).ConfigureAwait(false); // Construct a query string to find the twins with the EXACT model id and provided version. If EXACT is not specified, the query // call will get all twins with the same model id but that implement any version higher than the provided version string queryString = $"SELECT * FROM digitaltwins WHERE IS_OF_MODEL('{roomModelId}', EXACT) AND IsOccupied = true"; // act AsyncPageable <BasicDigitalTwin> asyncPageableResponse = client.QueryAsync <BasicDigitalTwin>(queryString); // assert // It takes a few seconds for the service to be able to fetch digital twins through queries after being created. Hence, adding the retry logic var digitalTwinFound = false; await TestRetryHelper.RetryAsync <AsyncPageable <BasicDigitalTwin> >(async() => { await foreach (BasicDigitalTwin response in asyncPageableResponse) { digitalTwinFound = true; bool isOccupied = ((JsonElement)response.Contents["IsOccupied"]).GetBoolean(); isOccupied.Should().BeTrue(); break; } if (!digitalTwinFound) { throw new Exception($"Digital twin based on model Id {roomModelId} not found"); } return(null); }, s_retryCount, s_retryDelay); digitalTwinFound.Should().BeTrue(); } catch (Exception ex) { Assert.Fail($"Failure in executing a step in the test case: {ex.Message}."); } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomModelId)) { await client.DeleteModelAsync(roomModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
public async Task Query_PaginationWorks() { DigitalTwinsClient client = GetClient(); int pageSize = 5; string floorModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.FloorModelIdPrefix).ConfigureAwait(false); string roomModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomModelIdPrefix).ConfigureAwait(false); TimeSpan QueryWaitTimeout = TimeSpan.FromMinutes(1); // Wait at most one minute for the created twins to become queryable try { // Create room model string roomModel = TestAssetsHelper.GetRoomModelPayload(roomModelId, floorModelId); await CreateAndListModelsAsync(client, new List <string> { roomModel }).ConfigureAwait(false); // Create a room twin, with property "IsOccupied": true BasicDigitalTwin roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); for (int i = 0; i < pageSize * 2; i++) { string roomTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomTwinIdPrefix).ConfigureAwait(false); await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false); } string queryString = "SELECT * FROM digitaltwins"; // act CancellationTokenSource queryTimeoutCancellationToken = new CancellationTokenSource(QueryWaitTimeout); bool queryHasExpectedCount = false; while (!queryHasExpectedCount) { if (queryTimeoutCancellationToken.IsCancellationRequested) { throw new AssertionException($"Timed out waiting for at least {pageSize + 1} twins to be queryable"); } AsyncPageable <BasicDigitalTwin> asyncPageableResponse = client.QueryAsync <BasicDigitalTwin>(queryString, queryTimeoutCancellationToken.Token); int count = 0; await foreach (Page <BasicDigitalTwin> queriedTwinPage in asyncPageableResponse.AsPages(pageSizeHint: pageSize)) { count += queriedTwinPage.Values.Count; } // Once at least (page + 1) twins are query-able, then page size control can be tested. queryHasExpectedCount = count >= pageSize + 1; } // assert // Test that page size hint works, and that all returned pages either have the page size hint amount of // elements, or have no continuation token (signaling that it is the last page) int pageCount = 0; await foreach (Page <BasicDigitalTwin> page in client.QueryAsync <BasicDigitalTwin>(queryString).AsPages(pageSizeHint: pageSize)) { pageCount++; if (page.ContinuationToken != null) { page.Values.Count.Should().Be(pageSize, "Unexpected page size for a non-terminal page"); } } pageCount.Should().BeGreaterThan(1, "Expected more than one page of query results"); } catch (Exception ex) { Assert.Fail($"Failure in executing a step in the test case: {ex.Message}."); } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomModelId)) { await client.DeleteModelAsync(roomModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
static async Task Main(string[] args) { Console.WriteLine("Hello World!"); string clientId = "<clientId>"; string tenantId = "<tenatId>"; string adtInstanceUrl = "https://yourinstance"; var credentials = new InteractiveBrowserCredential(tenantId, clientId); DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credentials); Console.WriteLine($"Service client created – ready to go"); Console.WriteLine(); Console.WriteLine($"Upload a model"); var typeList = new List <string>(); string dtdl = File.ReadAllText("Models/SampleModel.json"); typeList.Add(dtdl); // Upload the model to the service try { await client.CreateModelsAsync(typeList); } catch (RequestFailedException rex) { Console.WriteLine($"Load model: {rex.Status}:{rex.Message}"); } // Read a list of models back from the service AsyncPageable <ModelData> modelDataList = client.GetModelsAsync(); await foreach (ModelData md in modelDataList) { Console.WriteLine($"Type name: {md.DisplayName}: {md.Id}"); } // Initialize twin data BasicDigitalTwin twinData = new BasicDigitalTwin(); twinData.Metadata.ModelId = "dtmi:com:contoso:SampleModel;1"; twinData.CustomProperties.Add("data", $"Hello World!"); string prefix = "sampleTwin-"; for (int i = 0; i < 3; i++) { try { twinData.Id = $"{prefix}{i}"; await client.CreateDigitalTwinAsync($"{prefix}{i}", JsonSerializer.Serialize(twinData)); Console.WriteLine($"Created twin: {prefix}{i}"); } catch (RequestFailedException rex) { Console.WriteLine($"Create twin error: {rex.Status}:{rex.Message}"); } } // Connect the twins with relationships await CreateRelationship(client, "sampleTwin-0", "sampleTwin-1"); await CreateRelationship(client, "sampleTwin-0", "sampleTwin-2"); //List the relationships await ListRelationships(client, "sampleTwin-0"); // Run a query AsyncPageable <string> result = client.QueryAsync("Select * From DigitalTwins"); await foreach (string twin in result) { object jsonObj = JsonSerializer.Deserialize <object>(twin); string prettyTwin = JsonSerializer.Serialize(jsonObj, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine(prettyTwin); Console.WriteLine("---------------"); } }
// <Async_signature> static async Task Main(string[] args) { // </Async_signature> Console.WriteLine("Hello World!"); // <Authentication_code> string adtInstanceUrl = "https://<your-Azure-Digital-Twins-instance-hostName>"; var credential = new DefaultAzureCredential(); var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential); Console.WriteLine($"Service client created – ready to go"); // </Authentication_code> // <Model_code> Console.WriteLine(); Console.WriteLine("Upload a model"); string dtdl = File.ReadAllText("SampleModel.json"); var models = new List <string> { dtdl }; // Upload the model to the service // <Model_try_catch> try { await client.CreateModelsAsync(models); Console.WriteLine("Models uploaded to the instance:"); } catch (RequestFailedException e) { Console.WriteLine($"Upload model error: {e.Status}: {e.Message}"); } // </Model_try_catch> // <Print_model> // Read a list of models back from the service AsyncPageable <DigitalTwinsModelData> modelDataList = client.GetModelsAsync(); await foreach (DigitalTwinsModelData md in modelDataList) { Console.WriteLine($"Model: {md.Id}"); } // </Print_model> // </Model_code> // <Initialize_twins> var twinData = new BasicDigitalTwin(); twinData.Metadata.ModelId = "dtmi:example:SampleModel;1"; twinData.Contents.Add("data", $"Hello World!"); string prefix = "sampleTwin-"; for (int i = 0; i < 3; i++) { try { twinData.Id = $"{prefix}{i}"; await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(twinData.Id, twinData); Console.WriteLine($"Created twin: {twinData.Id}"); } catch (RequestFailedException e) { Console.WriteLine($"Create twin error: {e.Status}: {e.Message}"); } } // </Initialize_twins> // <Use_create_relationship> // Connect the twins with relationships await CreateRelationshipAsync(client, "sampleTwin-0", "sampleTwin-1"); await CreateRelationshipAsync(client, "sampleTwin-0", "sampleTwin-2"); // </Use_create_relationship> // <Use_list_relationships> //List the relationships await ListRelationshipsAsync(client, "sampleTwin-0"); // </Use_list_relationships> // <Query_twins> // Run a query for all twins string query = "SELECT * FROM digitaltwins"; AsyncPageable <BasicDigitalTwin> queryResult = client.QueryAsync <BasicDigitalTwin>(query); await foreach (BasicDigitalTwin twin in queryResult) { Console.WriteLine(JsonSerializer.Serialize(twin)); Console.WriteLine("---------------"); } // </Query_twins> }
static async Task Main(string[] args) { Console.WriteLine("Hello World!"); string adtInstanceUrl = "<youradturl>"; var credential = new DefaultAzureCredential(); DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), credential); Console.WriteLine($"Service client created – ready to go"); // uploading data Console.WriteLine(); Console.WriteLine($"Upload a model"); var typeList = new List <string>(); string dtdl = File.ReadAllText("new.json"); typeList.Add(dtdl); // Upload the model to the service try { await client.CreateModelsAsync(typeList); } catch (RequestFailedException rex) { Console.WriteLine($"Load model: {rex.Status}:{rex.Message}"); } // now lets add more models based on the one just uploaded // Initialize twin data BasicDigitalTwin twinData = new BasicDigitalTwin(); twinData.Metadata.ModelId = "dtmi:example:SampleModel;1"; twinData.Contents.Add("data", $"Hello World!"); string prefix = "sampleTwin-"; for (int i = 0; i < 3; i++) { try { twinData.Id = $"{prefix}{i}"; await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(twinData.Id, twinData); Console.WriteLine($"Created twin: {prefix}{i}"); } catch (RequestFailedException rex) { Console.WriteLine($"Create twin error: {rex.Status}:{rex.Message}"); } } // Connect the twins with relationships await CreateRelationship(client, "sampleTwin-0", "sampleTwin-1"); await CreateRelationship(client, "sampleTwin-0", "sampleTwin-2"); //List the relationships await ListRelationships(client, "sampleTwin-0"); // Run a query for all twins string query = "SELECT * FROM digitaltwins"; AsyncPageable <BasicDigitalTwin> result = client.QueryAsync <BasicDigitalTwin>(query); Console.WriteLine("---------------"); await foreach (BasicDigitalTwin twin in result) { Console.WriteLine(JsonSerializer.Serialize(twin)); Console.WriteLine("---------------"); } }
public async Task TestNewtonsoftObjectSerializerWithDigitalTwins() { DigitalTwinsClient defaultClient = GetClient(); string roomTwinId = await GetUniqueTwinIdAsync(defaultClient, TestAssetDefaults.RoomTwinIdPrefix).ConfigureAwait(false); string floorModelId = await GetUniqueModelIdAsync(defaultClient, TestAssetDefaults.FloorModelIdPrefix).ConfigureAwait(false); string roomModelId = await GetUniqueModelIdAsync(defaultClient, TestAssetDefaults.RoomModelIdPrefix).ConfigureAwait(false); try { // arrange // create room model string roomModel = TestAssetsHelper.GetRoomModelPayload(roomModelId, floorModelId); await CreateAndListModelsAsync(defaultClient, new List <string> { roomModel }).ConfigureAwait(false); // act // create room twin BasicDigitalTwin roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); await defaultClient.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false); // Create a client with NewtonsoftJsonObjectSerializer configured as the serializer. DigitalTwinsClient testClient = GetClient( new DigitalTwinsClientOptions { Serializer = new NewtonsoftJsonObjectSerializer() }); // Get digital twin using the simple DigitalTwin model annotated with Newtonsoft attributes SimpleNewtonsoftDtModel getResponse = await testClient.GetDigitalTwinAsync <SimpleNewtonsoftDtModel>(roomTwinId).ConfigureAwait(false); getResponse.Id.Should().NotBeNullOrEmpty("Digital twin ID should not be null or empty"); // Query DigitalTwins using the simple DigitalTwin model annotated with Newtonsoft attributes AsyncPageable <SimpleNewtonsoftDtModel> queryResponse = testClient.QueryAsync <SimpleNewtonsoftDtModel>("SELECT * FROM DIGITALTWINS"); await foreach (SimpleNewtonsoftDtModel twin in queryResponse) { twin.Id.Should().NotBeNullOrEmpty("Digital twin Id should not be null or empty"); } } finally { // cleanup try { // delete twin if (!string.IsNullOrWhiteSpace(roomTwinId)) { await defaultClient.DeleteDigitalTwinAsync(roomTwinId).ConfigureAwait(false); } // delete models if (!string.IsNullOrWhiteSpace(roomModelId)) { await defaultClient.DeleteModelAsync(roomModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
public static async Task Run( [EventHubTrigger("twins-event-hub", Connection = "EventHubAppSetting-Twins")] EventData myEventHubMessage, [EventHub("tsi-event-hub", Connection = "EventHubAppSetting-TSI")] IAsyncCollector <string> outputEvents, ILogger log) { if (adtServiceUrl == null) { log.LogError("Application setting \"ADT_SERVICE_URL\" not set"); return; } DefaultAzureCredential credentials = new DefaultAzureCredential(); dtClient = new DigitalTwinsClient(new Uri(adtServiceUrl), credentials, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); string capabilityTwinId = myEventHubMessage.Properties["cloudEvents:subject"].ToString(); JObject message = (JObject)JsonConvert.DeserializeObject(Encoding.UTF8.GetString(myEventHubMessage.Body)); log.LogInformation($"Reading event: '{message}' from twin '{capabilityTwinId}'."); // Get the twin from ADT that was updated to cause the incoming message // Query verifies that the twin is an instance of REC capability subclass List <BasicDigitalTwin> capabilityTwins = new List <BasicDigitalTwin>(); string capabilityTwinQuery = $"SELECT * FROM DIGITALTWINS DT WHERE IS_OF_MODEL(DT, 'dtmi:digitaltwins:rec_3_3:core:Capability;1') AND DT.$dtId = '{capabilityTwinId}'"; await foreach (BasicDigitalTwin returnedTwin in dtClient.QueryAsync <BasicDigitalTwin>(capabilityTwinQuery)) { capabilityTwins.Add(returnedTwin); break; } // If we get anything but a single result back from the above, something has gone wrong; the twin does not exist or is the wrong type if (capabilityTwins.Count != 1) { log.LogInformation($"The modified twin {capabilityTwinId} is not defined as a REC Capability in ADT."); return; } BasicDigitalTwin capabilityTwin = capabilityTwins.First(); // Extract name of capability twin. Only proceed if such a name exists. string capabilityName = ""; if (capabilityTwin.Contents.ContainsKey("name") && capabilityTwin.Contents["name"] is JsonElement) { capabilityName = ((JsonElement)capabilityTwin.Contents["name"]).ToString().Trim(); } if (capabilityName == "") { log.LogError($"Capability twin {capabilityTwinId} does not have a name assigned."); log.LogError(capabilityTwin.ToString()); return; } // Extract value from incoming message JSON patch. Only proceed if the patch assigns a value to /lastValue JToken capabilityValue = message["patch"].Children <JObject>() .Where( patch => patch.ContainsKey("path") && patch["path"].ToString() == "/lastValue" && patch.ContainsKey("op") && (patch["op"].ToString() == "replace" || patch["op"].ToString() == "add") && patch.ContainsKey("value")) .Select(patch => patch["value"]).FirstOrDefault(); if (capabilityValue == null) { log.LogInformation($"Incoming event does not contain a JSON patch for /lastValue."); return; } // At this stage, we have enough information to propagate the state to TSI await PropagateStateToTSI(capabilityTwinId, capabilityName, capabilityValue, outputEvents, log); // And also to Azure Maps await PropagateStateToAzureMapsAsync(capabilityTwinId, capabilityName, capabilityValue, log); }