public async Task DigitalTwins_Lifecycle() { DigitalTwinsClient client = GetClient(); string roomTwinId = await GetUniqueTwinIdAsync(client, TestAssetSettings.RoomTwinIdPrefix).ConfigureAwait(false); string floorModelId = await GetUniqueModelIdAsync(client, TestAssetSettings.FloorModelIdPrefix).ConfigureAwait(false); string roomModelId = await GetUniqueModelIdAsync(client, TestAssetSettings.RoomModelIdPrefix).ConfigureAwait(false); try { // arrange // create room model string roomModel = TestAssetsHelper.GetRoomModelPayload(roomModelId, floorModelId); await client.CreateModelsAsync(new List <string> { roomModel }).ConfigureAwait(false); // act // create room twin string roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); await client.CreateDigitalTwinAsync(roomTwinId, roomTwin).ConfigureAwait(false); // get twin await client.GetDigitalTwinAsync(roomTwinId).ConfigureAwait(false); // update twin string updateTwin = TestAssetsHelper.GetRoomTwinUpdatePayload(); await client.UpdateDigitalTwinAsync(roomTwinId, updateTwin).ConfigureAwait(false); // delete a twin await client.DeleteDigitalTwinAsync(roomTwinId).ConfigureAwait(false); // assert Func <Task> act = async() => { await client.GetDigitalTwinAsync(roomTwinId).ConfigureAwait(false); }; act.Should().Throw <RequestFailedException>() .And.Status.Should().Be((int)HttpStatusCode.NotFound); } finally { // cleanup 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}"); } } }
/// <summary> /// Create a twin with the specified properties /// </summary> public static async Task CreateTwin(DigitalTwinsClient client) { Console.Write("vehicleId: "); string vehicleID = Console.ReadLine(); Console.Write("modelId: "); string dtmi = Console.ReadLine(); try { Response <ModelData> res = client.GetModel(dtmi); string twinId = string.Format("{0}-{1}", res.Value.DisplayName.Values.ElementAt(0), vehicleID); Console.Write("twinId (suggest {0}): ", twinId); twinId = Console.ReadLine(); var twinData = new BasicDigitalTwin { Id = twinId, Metadata = { ModelId = dtmi, }, }; try { await client.CreateDigitalTwinAsync(twinData.Id, JsonSerializer.Serialize(twinData)); Console.WriteLine($"Twin '{twinId}' created successfully!"); } catch (RequestFailedException e) { Console.WriteLine($"Error {e.Status}: {e.Message}"); } catch (Exception ex) { Console.WriteLine($"Error: {ex}"); } } catch (RequestFailedException e) { Console.WriteLine($"Error {e.Status}: {e.Message}"); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } }
private async Task CreateModelsAndTwins(DigitalTwinsClient client, string wifiModelId, string roomWithWifiModelId, string wifiComponentName, string roomWithWifiTwinId) { // Generate the payload needed to create the WiFi component model. string wifiModel = TestAssetsHelper.GetWifiModelPayload(wifiModelId); // Generate the payload needed to create the room with WiFi model. string roomWithWifiModel = TestAssetsHelper.GetRoomWithWifiModelPayload(roomWithWifiModelId, wifiModelId, wifiComponentName); // Create the room and WiFi models. await client.CreateModelsAsync(new List <string> { roomWithWifiModel, wifiModel }).ConfigureAwait(false); // Generate the payload needed to create the room with WiFi twin. BasicDigitalTwin roomWithWifiTwin = TestAssetsHelper.GetRoomWithWifiTwinPayload(roomWithWifiModelId, wifiComponentName); // Create the room with WiFi component digital twin. await client.CreateDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId, roomWithWifiTwin).ConfigureAwait(false); }
public static async Task <string> FindOrCreateTwin(string dtmi, string regId, ILogger log) { // Create Digital Twin 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 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); }
/// <summary> /// Creates all twins specified in the \DTDL\DigitalTwins directory /// </summary> public async Task CreateAllTwinsAsync() { PrintHeader("CREATE DIGITAL TWINS"); Dictionary <string, string> twins = FileHelper.LoadAllFilesInPath(s_twinsPath); // Call APIs to create the twins. foreach (KeyValuePair <string, string> twin in twins) { try { Response <string> response = await client.CreateDigitalTwinAsync(twin.Key, twin.Value); Console.WriteLine($"Created digital twin {twin.Key}. Create response status: {response.GetRawResponse().Status}"); Console.WriteLine($"Body: {response?.Value}"); } catch (Exception ex) { FatalError($"Could not create digital twin {twin.Key} due to {ex}"); } } }
/// <summary> /// Creates all twins specified in the \DTDL\DigitalTwins directory /// </summary> public async Task CreateAllTwinsAsync() { PrintHeader("CREATE DIGITAL TWINS"); Dictionary <string, string> twins = FileHelper.LoadAllFilesInPath(s_twinsPath); // Call APIs to create the twins. foreach (KeyValuePair <string, string> twin in twins) { try { BasicDigitalTwin basicDigitalTwin = JsonSerializer.Deserialize <BasicDigitalTwin>(twin.Value); Response <BasicDigitalTwin> response = await client.CreateDigitalTwinAsync <BasicDigitalTwin>(twin.Key, basicDigitalTwin); Console.WriteLine($"Created digital twin '{twin.Key}'."); Console.WriteLine($"\tBody: {JsonSerializer.Serialize(response?.Value)}"); } catch (Exception ex) { FatalError($"Could not create digital twin '{twin.Key}' due to {ex}"); } } }
/// <summary> /// Creates a digital twin with Component and upates Component /// </summary> public async Task RunSamplesAsync(DigitalTwinsClient client) { PrintHeader("COMPONENT SAMPLE"); // For the purpose of this example we will create temporary models using a random model Ids. // We have to make sure these model Ids are unique within the DT instance. string componentModelId = await GetUniqueModelIdAsync(SamplesConstants.TemporaryComponentModelPrefix, client); string modelId = await GetUniqueModelIdAsync(SamplesConstants.TemporaryModelPrefix, client); string basicDtId = await GetUniqueTwinIdAsync(SamplesConstants.TemporaryTwinPrefix, client); string newComponentModelPayload = SamplesConstants.TemporaryComponentModelPayload .Replace(SamplesConstants.ComponentId, componentModelId); string newModelPayload = SamplesConstants.TemporaryModelWithComponentPayload .Replace(SamplesConstants.ModelId, modelId) .Replace(SamplesConstants.ComponentId, componentModelId); // Then we create models Response <IReadOnlyList <Models.ModelData> > createModelsResponse = await client.CreateModelsAsync( new[] { newComponentModelPayload, newModelPayload }); Console.WriteLine($"Created models with Ids {componentModelId} and {modelId}. Response status: {createModelsResponse.GetRawResponse().Status}."); #region Snippet:DigitalTwinsSampleCreateBasicTwin // Create digital twin with component payload using the BasicDigitalTwin serialization helper var basicTwin = new BasicDigitalTwin { Id = basicDtId, // model Id of digital twin Metadata = { ModelId = modelId }, CustomProperties = { // digital twin properties { "Prop1", "Value1" }, { "Prop2", 987 }, // component { "Component1", new ModelProperties { // component properties CustomProperties = { { "ComponentProp1", "Component value 1" }, { "ComponentProp2", 123 }, }, } }, }, }; string basicDtPayload = JsonSerializer.Serialize(basicTwin); Response <string> createBasicDtResponse = await client.CreateDigitalTwinAsync(basicDtId, basicDtPayload); Console.WriteLine($"Created digital twin with Id {basicDtId}. Response status: {createBasicDtResponse.GetRawResponse().Status}."); #endregion Snippet:DigitalTwinsSampleCreateBasicTwin // You can also get a digital twin and deserialize it into a BasicDigitalTwin. // It works well for basic stuff, but as you can see it gets more difficult when delving into // more complex properties, like components. #region Snippet:DigitalTwinsSampleGetBasicDigitalTwin Response <string> getBasicDtResponse = await client.GetDigitalTwinAsync(basicDtId); if (getBasicDtResponse.GetRawResponse().Status == (int)HttpStatusCode.OK) { BasicDigitalTwin basicDt = JsonSerializer.Deserialize <BasicDigitalTwin>(getBasicDtResponse.Value); // Must cast Component1 as a JsonElement and get its raw text in order to deserialize it as a dictionary string component1RawText = ((JsonElement)basicDt.CustomProperties["Component1"]).GetRawText(); IDictionary <string, object> component1 = JsonSerializer.Deserialize <IDictionary <string, object> >(component1RawText); Console.WriteLine($"Retrieved and deserialized digital twin {basicDt.Id}:\n\t" + $"ETag: {basicDt.ETag}\n\t" + $"Prop1: {basicDt.CustomProperties["Prop1"]}\n\t" + $"Prop2: {basicDt.CustomProperties["Prop2"]}\n\t" + $"ComponentProp1: {component1["ComponentProp1"]}\n\t" + $"ComponentProp2: {component1["ComponentProp2"]}"); } #endregion Snippet:DigitalTwinsSampleGetBasicDigitalTwin string customDtId = await GetUniqueTwinIdAsync(SamplesConstants.TemporaryTwinPrefix, client); // Alternatively, you can create your own custom data types to serialize and deserialize your digital twins. // By specifying your properties and types directly, it requires less code or knowledge of the type for // interaction. #region Snippet:DigitalTwinsSampleCreateCustomTwin var customTwin = new CustomDigitalTwin { Id = customDtId, Metadata = { ModelId = modelId }, Prop1 = "Prop1 val", Prop2 = 987, Component1 = new Component1 { ComponentProp1 = "Component prop1 val", ComponentProp2 = 123, } }; string dt2Payload = JsonSerializer.Serialize(customTwin); Response <string> createCustomDtResponse = await client.CreateDigitalTwinAsync(customDtId, dt2Payload); Console.WriteLine($"Created digital twin with Id {customDtId}. Response status: {createCustomDtResponse.GetRawResponse().Status}."); #endregion Snippet:DigitalTwinsSampleCreateCustomTwin // Getting and deserializing a digital twin into a custom data type is extremely easy. // Custom types provide the best possible experience. #region Snippet:DigitalTwinsSampleGetCustomDigitalTwin Response <string> getCustomDtResponse = await client.GetDigitalTwinAsync(customDtId); if (getCustomDtResponse.GetRawResponse().Status == (int)HttpStatusCode.OK) { CustomDigitalTwin customDt = JsonSerializer.Deserialize <CustomDigitalTwin>(getCustomDtResponse.Value); Console.WriteLine($"Retrieved and deserialized digital twin {customDt.Id}:\n\t" + $"ETag: {customDt.ETag}\n\t" + $"Prop1: {customDt.Prop1}\n\t" + $"Prop2: {customDt.Prop2}\n\t" + $"ComponentProp1: {customDt.Component1.ComponentProp1}\n\t" + $"ComponentProp2: {customDt.Component1.ComponentProp2}"); } #endregion Snippet:DigitalTwinsSampleGetCustomDigitalTwin #region Snippet:DigitalTwinsSampleUpdateComponent // Update Component1 by replacing the property ComponentProp1 value var componentUpdateUtility = new UpdateOperationsUtility(); componentUpdateUtility.AppendReplaceOp("/ComponentProp1", "Some new value"); string updatePayload = componentUpdateUtility.Serialize(); Response <string> response = await client.UpdateComponentAsync(basicDtId, "Component1", updatePayload); Console.WriteLine($"Updated component for digital twin with Id {basicDtId}. Response status: {response.GetRawResponse().Status}"); #endregion Snippet:DigitalTwinsSampleUpdateComponent // Get Component #region Snippet:DigitalTwinsSampleGetComponent response = await client.GetComponentAsync(basicDtId, SamplesConstants.ComponentPath); Console.WriteLine($"Retrieved component for digital twin with Id {basicDtId}. Response status: {response.GetRawResponse().Status}"); #endregion Snippet:DigitalTwinsSampleGetComponent // Clean up try { await client.DeleteDigitalTwinAsync(basicDtId); await client.DeleteDigitalTwinAsync(customDtId); } catch (RequestFailedException ex) { Console.WriteLine($"Failed to delete digital twin due to {ex}"); } try { await client.DeleteModelAsync(modelId); await client.DeleteModelAsync(componentModelId); } catch (RequestFailedException ex) { Console.WriteLine($"Failed to delete models due to {ex}"); } }
/// <summary> /// Creates two digital twins, and connect them with relationships. /// </summary> public async Task RunSamplesAsync(DigitalTwinsClient 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("RELATIONSHIP SAMPLE"); string sampleBuildingModelId = "dtmi:com:samples:SampleBuilding;1"; string sampleFloorModelId = "dtmi:com:samples:SampleFloor;1"; await ModelLifecycleSamples.TryDeleteModelAsync(client, sampleBuildingModelId); await ModelLifecycleSamples.TryDeleteModelAsync(client, sampleFloorModelId); // Create a building digital twin model. string buildingModelPayload = SamplesConstants.TemporaryModelWithRelationshipPayload .Replace(SamplesConstants.RelationshipTargetModelId, sampleFloorModelId) .Replace(SamplesConstants.ModelId, sampleBuildingModelId) .Replace(SamplesConstants.ModelDisplayName, "Building") .Replace(SamplesConstants.RelationshipName, "contains"); await client.CreateModelsAsync( new[] { buildingModelPayload }); Console.WriteLine($"Created model '{sampleBuildingModelId}'."); // Create a floor digital twin model. string floorModelPayload = SamplesConstants.TemporaryModelWithRelationshipPayload .Replace(SamplesConstants.RelationshipTargetModelId, sampleBuildingModelId) .Replace(SamplesConstants.ModelId, sampleFloorModelId) .Replace(SamplesConstants.ModelDisplayName, "Floor") .Replace(SamplesConstants.RelationshipName, "containedIn"); await client.CreateModelsAsync(new[] { floorModelPayload }); Console.WriteLine($"Created model '{sampleFloorModelId}'"); // Create a building digital twin. var buildingDigitalTwin = new BasicDigitalTwin { Id = "buildingTwinId", Metadata = { ModelId = sampleBuildingModelId } }; Response <BasicDigitalTwin> createDigitalTwinResponse = await client.CreateDigitalTwinAsync <BasicDigitalTwin>("buildingTwinId", buildingDigitalTwin); Console.WriteLine($"Created twin '{createDigitalTwinResponse.Value.Id}'."); // Create a floor digital. var floorDigitalTwin = new BasicDigitalTwin { Id = "floorTwinId", Metadata = { ModelId = sampleFloorModelId } }; Response <BasicDigitalTwin> createFloorDigitalTwinResponse = await client.CreateDigitalTwinAsync <BasicDigitalTwin>("floorTwinId", floorDigitalTwin); Console.WriteLine($"Created twin '{createFloorDigitalTwinResponse.Value.Id}'."); // Create a relationship between building and floor using the BasicRelationship serialization helper. #region Snippet:DigitalTwinsSampleCreateBasicRelationship var buildingFloorRelationshipPayload = new BasicRelationship { Id = "buildingFloorRelationshipId", SourceId = "buildingTwinId", TargetId = "floorTwinId", Name = "contains", CustomProperties = { { "Prop1", "Prop1 value" }, { "Prop2", 6 } } }; Response <BasicRelationship> createBuildingFloorRelationshipResponse = await client .CreateRelationshipAsync <BasicRelationship>("buildingTwinId", "buildingFloorRelationshipId", buildingFloorRelationshipPayload); Console.WriteLine($"Created a digital twin relationship '{createBuildingFloorRelationshipResponse.Value.Id}' " + $"from twin '{createBuildingFloorRelationshipResponse.Value.SourceId}' to twin '{createBuildingFloorRelationshipResponse.Value.TargetId}'."); #endregion Snippet:DigitalTwinsSampleCreateBasicRelationship // You can get a relationship as a BasicRelationship type. #region Snippet:DigitalTwinsSampleGetBasicRelationship Response <BasicRelationship> getBasicRelationshipResponse = await client.GetRelationshipAsync <BasicRelationship>( "buildingTwinId", "buildingFloorRelationshipId"); if (getBasicRelationshipResponse.GetRawResponse().Status == (int)HttpStatusCode.OK) { BasicRelationship basicRelationship = getBasicRelationshipResponse.Value; Console.WriteLine($"Retrieved relationship '{basicRelationship.Id}' from twin {basicRelationship.SourceId}.\n\t" + $"Prop1: {basicRelationship.CustomProperties["Prop1"]}\n\t" + $"Prop2: {basicRelationship.CustomProperties["Prop2"]}"); } #endregion Snippet:DigitalTwinsSampleGetBasicRelationship // Alternatively, you can create your own custom data types and use these types when calling into the APIs. // This requires less code or knowledge of the type for interaction. // Create a relationship between floorTwinId and buildingTwinId using a custom data type. #region Snippet:DigitalTwinsSampleCreateCustomRelationship var floorBuildingRelationshipPayload = new CustomRelationship { Id = "floorBuildingRelationshipId", SourceId = "floorTwinId", TargetId = "buildingTwinId", Name = "containedIn", Prop1 = "Prop1 val", Prop2 = 4 }; Response <CustomRelationship> createCustomRelationshipResponse = await client .CreateRelationshipAsync <CustomRelationship>("floorTwinId", "floorBuildingRelationshipId", floorBuildingRelationshipPayload); Console.WriteLine($"Created a digital twin relationship '{createCustomRelationshipResponse.Value.Id}' " + $"from twin '{createCustomRelationshipResponse.Value.SourceId}' to twin '{createCustomRelationshipResponse.Value.TargetId}'."); #endregion Snippet:DigitalTwinsSampleCreateCustomRelationship // Getting a relationship as a custom data type is extremely easy. #region Snippet:DigitalTwinsSampleGetCustomRelationship Response <CustomRelationship> getCustomRelationshipResponse = await client.GetRelationshipAsync <CustomRelationship>( "floorTwinId", "floorBuildingRelationshipId"); CustomRelationship getCustomRelationship = getCustomRelationshipResponse.Value; Console.WriteLine($"Retrieved and deserialized relationship '{getCustomRelationship.Id}' from twin '{getCustomRelationship.SourceId}'.\n\t" + $"Prop1: {getCustomRelationship.Prop1}\n\t" + $"Prop2: {getCustomRelationship.Prop2}"); #endregion Snippet:DigitalTwinsSampleGetCustomRelationship // Get all relationships in the graph where buildingTwinId is the source of the relationship. #region Snippet:DigitalTwinsSampleGetAllRelationships AsyncPageable <string> relationships = client.GetRelationshipsAsync("buildingTwinId"); await foreach (var relationshipJson in relationships) { BasicRelationship relationship = JsonSerializer.Deserialize <BasicRelationship>(relationshipJson); Console.WriteLine($"Retrieved relationship '{relationship.Id}' with source {relationship.SourceId}' and " + $"target {relationship.TargetId}.\n\t" + $"Prop1: {relationship.CustomProperties["Prop1"]}\n\t" + $"Prop2: {relationship.CustomProperties["Prop2"]}"); } #endregion Snippet:DigitalTwinsSampleGetAllRelationships // Get all incoming relationships in the graph where buildingTwinId is the target of the relationship. #region Snippet:DigitalTwinsSampleGetIncomingRelationships AsyncPageable <IncomingRelationship> incomingRelationships = client.GetIncomingRelationshipsAsync("buildingTwinId"); await foreach (IncomingRelationship incomingRelationship in incomingRelationships) { Console.WriteLine($"Found an incoming relationship '{incomingRelationship.RelationshipId}' from '{incomingRelationship.SourceId}'."); } #endregion Snippet:DigitalTwinsSampleGetIncomingRelationships // Delete the contains relationship, created earlier in the sample code, from building to floor. #region Snippet:DigitalTwinsSampleDeleteRelationship await client.DeleteRelationshipAsync("buildingTwinId", "buildingFloorRelationshipId"); Console.WriteLine($"Deleted relationship 'buildingFloorRelationshipId'."); #endregion Snippet:DigitalTwinsSampleDeleteRelationship // Delete the containedIn relationship, created earlier in the sample code, from floor to building. await client.DeleteRelationshipAsync("floorTwinId", "floorBuildingRelationshipId"); Console.WriteLine($"Deleted relationship 'floorBuildingRelationshipId'."); // Clean up. try { // Delete all twins await client.DeleteDigitalTwinAsync("buildingTwinId"); await client.DeleteDigitalTwinAsync("floorTwinId"); } catch (RequestFailedException ex) { Console.WriteLine($"Failed to delete twin due to {ex}."); } try { await client.DeleteModelAsync(sampleBuildingModelId); await client.DeleteModelAsync(sampleFloorModelId); } catch (RequestFailedException ex) { Console.WriteLine($"Failed to delete model 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 Component_Lifecycle() { // arrange DigitalTwinsClient client = GetClient(); string wifiModelId = await GetUniqueModelIdAsync(client, TestAssetSettings.WifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiModelId = await GetUniqueModelIdAsync(client, TestAssetSettings.RoomWithWifiModelIdPrefix).ConfigureAwait(false); string roomWithWifiTwinId = await GetUniqueTwinIdAsync(client, TestAssetSettings.RoomWithWifiTwinIdPrefix).ConfigureAwait(false); string wifiComponentName = "wifiAccessPoint"; try { // CREATE // create roomWithWifi model string wifiModel = TestAssetsHelper.GetWifiModelPayload(wifiModelId); // create wifi model string roomWithWifiModel = TestAssetsHelper.GetRoomWithWifiModelPayload(roomWithWifiModelId, wifiModelId, wifiComponentName); await client.CreateModelsAsync(new List <string> { roomWithWifiModel, wifiModel }).ConfigureAwait(false); // create room digital twin string roomWithWifiTwin = TestAssetsHelper.GetRoomWithWifiTwinPayload(roomWithWifiModelId, wifiModelId, wifiComponentName); await client.CreateDigitalTwinAsync(roomWithWifiTwinId, roomWithWifiTwin); // Get the component Response <string> getComponentResponse = await client .GetComponentAsync( roomWithWifiTwinId, wifiComponentName) .ConfigureAwait(false); // The response to the GET request should be 200 (OK) getComponentResponse.GetRawResponse().Status.Should().Be((int)HttpStatusCode.OK); // Patch component Response <string> updateComponentResponse = await client .UpdateComponentAsync( roomWithWifiTwinId, wifiComponentName, TestAssetsHelper.GetWifiComponentUpdatePayload()) .ConfigureAwait(false); // The response to the Patch request should be 204 (No content) updateComponentResponse.GetRawResponse().Status.Should().Be((int)HttpStatusCode.NoContent); } finally { // clean up try { if (!string.IsNullOrWhiteSpace(roomWithWifiTwinId)) { await client.DeleteDigitalTwinAsync(roomWithWifiTwinId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(roomWithWifiModelId)) { await client.DeleteModelAsync(roomWithWifiModelId).ConfigureAwait(false); } if (!string.IsNullOrWhiteSpace(wifiModelId)) { await client.DeleteModelAsync(wifiModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
public async Task Relationships_Lifecycle() { // arrange DigitalTwinsClient client = GetClient(); var floorContainsRoomRelationshipId = "FloorToRoomRelationship"; var floorCooledByHvacRelationshipId = "FloorToHvacRelationship"; var hvacCoolsFloorRelationshipId = "HvacToFloorRelationship"; var roomContainedInFloorRelationshipId = "RoomToFloorRelationship"; string floorModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.FloorModelIdPrefix).ConfigureAwait(false); string roomModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomModelIdPrefix).ConfigureAwait(false); string hvacModelId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.HvacModelIdPrefix).ConfigureAwait(false); string floorTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.FloorTwinIdPrefix).ConfigureAwait(false); string roomTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomTwinIdPrefix).ConfigureAwait(false); string hvacTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.HvacTwinIdPrefix).ConfigureAwait(false); try { // create floor, room and hvac model string floorModel = TestAssetsHelper.GetFloorModelPayload(floorModelId, roomModelId, hvacModelId); string roomModel = TestAssetsHelper.GetRoomModelPayload(roomModelId, floorModelId); string hvacModel = TestAssetsHelper.GetHvacModelPayload(hvacModelId, floorModelId); await client.CreateModelsAsync(new List <string> { floorModel, roomModel, hvacModel }).ConfigureAwait(false); // create floor twin BasicDigitalTwin floorTwin = TestAssetsHelper.GetFloorTwinPayload(floorModelId); await client.CreateDigitalTwinAsync <BasicDigitalTwin>(floorTwinId, floorTwin).ConfigureAwait(false); // Create room twin BasicDigitalTwin roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); await client.CreateDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false); // create hvac twin BasicDigitalTwin hvacTwin = TestAssetsHelper.GetHvacTwinPayload(hvacModelId); await client.CreateDigitalTwinAsync <BasicDigitalTwin>(hvacTwinId, hvacTwin).ConfigureAwait(false); BasicRelationship floorContainsRoomPayload = TestAssetsHelper.GetRelationshipWithPropertyPayload(roomTwinId, ContainsRelationship, "isAccessRestricted", true); BasicRelationship floorTwinCoolsRelationshipPayload = TestAssetsHelper.GetRelationshipPayload(floorTwinId, CoolsRelationship); BasicRelationship floorTwinContainedInRelationshipPayload = TestAssetsHelper.GetRelationshipPayload(floorTwinId, ContainedInRelationship); BasicRelationship floorCooledByHvacPayload = TestAssetsHelper.GetRelationshipPayload(hvacTwinId, CooledByRelationship); JsonPatchDocument floorContainsRoomUpdatePayload = new JsonPatchDocument(); floorContainsRoomUpdatePayload.AppendReplace("/isAccessRestricted", false); // CREATE relationships // create Relationship from Floor -> Room await client .CreateRelationshipAsync <BasicRelationship>( floorTwinId, floorContainsRoomRelationshipId, floorContainsRoomPayload) .ConfigureAwait(false); // create Relationship from Floor -> Hvac await client .CreateRelationshipAsync <BasicRelationship>( floorTwinId, floorCooledByHvacRelationshipId, floorCooledByHvacPayload) .ConfigureAwait(false); // create Relationship from Hvac -> Floor await client .CreateRelationshipAsync <BasicRelationship>( hvacTwinId, hvacCoolsFloorRelationshipId, floorTwinCoolsRelationshipPayload) .ConfigureAwait(false); // create Relationship from Room -> Floor await client .CreateRelationshipAsync <BasicRelationship>( roomTwinId, roomContainedInFloorRelationshipId, floorTwinContainedInRelationshipPayload) .ConfigureAwait(false); // UPDATE relationships // create Relationship from Floor -> Room await client .UpdateRelationshipAsync( floorTwinId, floorContainsRoomRelationshipId, floorContainsRoomUpdatePayload) .ConfigureAwait(false); // GET relationship Response <BasicRelationship> containsRelationshipId = await client .GetRelationshipAsync <BasicRelationship>( floorTwinId, floorContainsRoomRelationshipId) .ConfigureAwait(false); // LIST incoming relationships AsyncPageable <IncomingRelationship> incomingRelationships = client.GetIncomingRelationshipsAsync(floorTwinId); int numberOfIncomingRelationshipsToFloor = 0; await foreach (IncomingRelationship relationship in incomingRelationships) { ++numberOfIncomingRelationshipsToFloor; } numberOfIncomingRelationshipsToFloor.Should().Be(2, "floor has incoming relationships from room and hvac"); // LIST relationships AsyncPageable <string> floorRelationships = client.GetRelationshipsAsync(floorTwinId); int numberOfFloorRelationships = 0; await foreach (var relationship in floorRelationships) { ++numberOfFloorRelationships; } numberOfFloorRelationships.Should().Be(2, "floor has an relationship to room and hvac"); // LIST relationships by name AsyncPageable <string> roomTwinRelationships = client .GetRelationshipsAsync( roomTwinId, ContainedInRelationship); containsRelationshipId.Value.Id.Should().Be(floorContainsRoomRelationshipId); int numberOfRelationships = 0; await foreach (var relationship in roomTwinRelationships) { ++numberOfRelationships; } numberOfRelationships.Should().Be(1, "room has only one containedIn relationship to floor"); await client .DeleteRelationshipAsync( floorTwinId, floorContainsRoomRelationshipId) .ConfigureAwait(false); await client .DeleteRelationshipAsync( roomTwinId, roomContainedInFloorRelationshipId) .ConfigureAwait(false); await client .DeleteRelationshipAsync( floorTwinId, floorCooledByHvacRelationshipId) .ConfigureAwait(false); await client .DeleteRelationshipAsync( hvacTwinId, hvacCoolsFloorRelationshipId) .ConfigureAwait(false); Func <Task> act = async() => { await client .GetRelationshipAsync <BasicRelationship>( floorTwinId, floorContainsRoomRelationshipId) .ConfigureAwait(false); }; act.Should().Throw <RequestFailedException>() .And.Status.Should().Be((int)HttpStatusCode.NotFound); act = async() => { await client .GetRelationshipAsync <BasicRelationship>( roomTwinId, roomContainedInFloorRelationshipId) .ConfigureAwait(false); }; act.Should().Throw <RequestFailedException>(). And.Status.Should().Be((int)HttpStatusCode.NotFound); act = async() => { await client .GetRelationshipAsync <BasicRelationship>( floorTwinId, floorCooledByHvacRelationshipId) .ConfigureAwait(false); }; act.Should().Throw <RequestFailedException>(). And.Status.Should().Be((int)HttpStatusCode.NotFound); act = async() => { await client .GetRelationshipAsync <BasicRelationship>( hvacTwinId, hvacCoolsFloorRelationshipId) .ConfigureAwait(false); }; act.Should().Throw <RequestFailedException>() .And.Status.Should().Be((int)HttpStatusCode.NotFound); } finally { // clean up try { await Task .WhenAll( client.DeleteDigitalTwinAsync(floorTwinId), client.DeleteDigitalTwinAsync(roomTwinId), client.DeleteDigitalTwinAsync(hvacTwinId), client.DeleteModelAsync(hvacModelId), client.DeleteModelAsync(floorModelId), client.DeleteModelAsync(roomModelId)) .ConfigureAwait(false); } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
public async Task Relationships_PaginationWorks() { DigitalTwinsClient client = GetClient(); string floorModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.FloorModelIdPrefix).ConfigureAwait(false); string roomModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomModelIdPrefix).ConfigureAwait(false); string hvacModelId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.HvacModelIdPrefix).ConfigureAwait(false); string floorTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.FloorTwinIdPrefix).ConfigureAwait(false); string roomTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomTwinIdPrefix).ConfigureAwait(false); string hvacTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.HvacTwinIdPrefix).ConfigureAwait(false); try { // create floor, room and hvac model string floorModel = TestAssetsHelper.GetFloorModelPayload(floorModelId, roomModelId, hvacModelId); string roomModel = TestAssetsHelper.GetRoomModelPayload(roomModelId, floorModelId); string hvacModel = TestAssetsHelper.GetHvacModelPayload(hvacModelId, floorModelId); await client.CreateModelsAsync(new List <string> { floorModel, roomModel, hvacModel }).ConfigureAwait(false); // create floor twin BasicDigitalTwin floorTwin = TestAssetsHelper.GetFloorTwinPayload(floorModelId); await client.CreateDigitalTwinAsync <BasicDigitalTwin>(floorTwinId, floorTwin).ConfigureAwait(false); // Create room twin BasicDigitalTwin roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); await client.CreateDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false); BasicRelationship floorContainsRoomPayload = TestAssetsHelper.GetRelationshipWithPropertyPayload(roomTwinId, ContainsRelationship, "isAccessRestricted", true); BasicRelationship floorTwinContainedInRelationshipPayload = TestAssetsHelper.GetRelationshipPayload(floorTwinId, ContainedInRelationship); // For the sake of test simplicity, we'll just add multiple relationships from the same floor to the same room. for (int i = 0; i < bulkRelationshipCount; i++) { var floorContainsRoomRelationshipId = $"FloorToRoomRelationship-{GetRandom()}"; // create Relationship from Floor -> Room await client .CreateRelationshipAsync <BasicRelationship>( floorTwinId, floorContainsRoomRelationshipId, floorContainsRoomPayload) .ConfigureAwait(false); } // For the sake of test simplicity, we'll just add multiple relationships from the same room to the same floor. for (int i = 0; i < bulkRelationshipCount; i++) { var roomContainedInFloorRelationshipId = $"RoomToFloorRelationship-{GetRandom()}"; // create Relationship from Room -> Floor await client .CreateRelationshipAsync <BasicRelationship>( roomTwinId, roomContainedInFloorRelationshipId, floorTwinContainedInRelationshipPayload) .ConfigureAwait(false); } // LIST incoming relationships by page AsyncPageable <IncomingRelationship> incomingRelationships = client.GetIncomingRelationshipsAsync(floorTwinId); int incomingRelationshipPageCount = 0; await foreach (Page <IncomingRelationship> incomingRelationshipPage in incomingRelationships.AsPages()) { incomingRelationshipPageCount++; if (incomingRelationshipPage.ContinuationToken != null) { incomingRelationshipPage.Values.Count.Should().Be(defaultRelationshipPageSize, "Unexpected page size for a non-terminal page"); } } incomingRelationshipPageCount.Should().BeGreaterThan(1, "Expected more than one page of incoming relationships"); // LIST outgoing relationships by page AsyncPageable <string> outgoingRelationships = client.GetRelationshipsAsync(floorTwinId); int outgoingRelationshipPageCount = 0; await foreach (Page <string> outgoingRelationshipPage in outgoingRelationships.AsPages()) { outgoingRelationshipPageCount++; if (outgoingRelationshipPage.ContinuationToken != null) { outgoingRelationshipPage.Values.Count.Should().Be(defaultRelationshipPageSize, "Unexpected page size for a non-terminal page"); } } outgoingRelationshipPageCount.Should().BeGreaterThan(1, "Expected more than one page of outgoing relationships"); } finally { // clean up try { await Task .WhenAll( client.DeleteDigitalTwinAsync(floorTwinId), client.DeleteDigitalTwinAsync(roomTwinId), client.DeleteDigitalTwinAsync(hvacTwinId), client.DeleteModelAsync(hvacModelId), client.DeleteModelAsync(floorModelId), client.DeleteModelAsync(roomModelId)) .ConfigureAwait(false); } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
private static async Task HandleDeviceMessage(DeviceMessage deviceCommandMessage, DeviceClient primaryClient, DeviceClient secondaryClient, string firstHubName, string secondHubName) { // this section demonstrates how to parse a non-binary DeviceCommandMessage that was sent down. // Later more advanced kits will discuss using binary payloads as another possibility. string rawContent; using (StreamReader reader = new StreamReader(deviceCommandMessage.BodyStream)) { rawContent = await reader.ReadToEndAsync(); } //DeviceCommandMessage parsedMessage = JsonConvert.DeserializeObject<DeviceCommandMessage>(rawContent); DeviceCommandMessage parsedMessage = System.Text.Json.JsonSerializer.Deserialize <DeviceCommandMessage>(rawContent); // Create a secret client using the DefaultAzureCredential DefaultAzureCredential cred = new DefaultAzureCredential(); DigitalTwinsClient dtcli = new DigitalTwinsClient(new Uri("https://mobility-vss.api.wus2.digitaltwins.azure.net"), cred); BasicDigitalTwin twinData = new BasicDigitalTwin(); JsonElement ele = (JsonElement)parsedMessage.Payload; twinData.Id = ele.GetProperty("$dtId").ToString(); twinData.Metadata.ModelId = ele.GetProperty("$metadata").GetProperty("$model").ToString(); await dtcli.CreateDigitalTwinAsync(twinData.Id, System.Text.Json.JsonSerializer.Serialize(twinData)); await primaryClient.CompleteAsync(deviceCommandMessage); Console.WriteLine("The received command name is: " + parsedMessage.CommandName); Console.Write("Enter a response string:\n>"); string responseString = Console.ReadLine(); // construct a basic Device Telemetry Message with a minimal set of fields. This will be used to respond to the command. DeviceTelemetryMessage telemetryMessage = new DeviceTelemetryMessage { TelemetryName = parsedMessage.CommandName, Payload = new { rawContent }, Priority = MessagePriority.Normal, CorrelationId = parsedMessage.CorrelationId // setting the correlation ID allows the platform to recognize this is a response to the previous device command message. }; // construct the actual IoT message. Setting the content type is necessary for prioritization to function properly within CVS. using (DeviceMessage deviceMessage = new DeviceMessage(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(telemetryMessage)))) { deviceMessage.ContentType = "application/json"; // enqueues the event within IoTHub. The completion of this event means that it has been enqueued to the cloud, but // does not imply that the cloud has actually processed the telemetry message yet. try { await primaryClient.SendEventAsync(deviceMessage); Console.WriteLine($"Sent telemetry message to {firstHubName} IoTHub in response!"); } catch (Exception) { await secondaryClient.SendEventAsync(deviceMessage); Console.WriteLine($"Sent telemetry message to {secondHubName} IoTHub in response!"); } } }
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("---------------"); } }
public async Task DigitalTwins_Lifecycle() { DigitalTwinsClient client = GetClient(); string roomTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.RoomTwinIdPrefix).ConfigureAwait(false); 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); // act // create room twin BasicDigitalTwin roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId); await client.CreateDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false); // get twin await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomTwinId).ConfigureAwait(false); // update twin JsonPatchDocument updateTwinPatchDocument = new JsonPatchDocument(); updateTwinPatchDocument.AppendAdd("/Humidity", 30); updateTwinPatchDocument.AppendReplace("/Temperature", 70); updateTwinPatchDocument.AppendRemove("/EmployeeId"); var requestOptions = new UpdateDigitalTwinOptions { IfMatch = "*" }; await client.UpdateDigitalTwinAsync(roomTwinId, updateTwinPatchDocument, requestOptions).ConfigureAwait(false); // delete a twin await client.DeleteDigitalTwinAsync(roomTwinId).ConfigureAwait(false); // assert Func <Task> act = async() => { await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomTwinId).ConfigureAwait(false); }; act.Should().Throw <RequestFailedException>() .And.Status.Should().Be((int)HttpStatusCode.NotFound); } finally { // cleanup try { if (!string.IsNullOrWhiteSpace(roomModelId)) { await client.DeleteModelAsync(roomModelId).ConfigureAwait(false); } } catch (Exception ex) { Assert.Fail($"Test clean up failed: {ex.Message}"); } } }
/// <summary> /// Create a temporary component model, twin model and digital twin instance. /// Publish a telemetry message and a component telemetry message to the digital twin instance. /// </summary> public async Task RunSamplesAsync(DigitalTwinsClient client) { PrintHeader("PUBLISH TELEMETRY MESSAGE SAMPLE"); // For the purpose of this example we will create temporary models using a random model Ids. // We will also create temporary twin instances to publish the telemetry to. string componentModelId = await GetUniqueModelIdAsync(SamplesConstants.TemporaryComponentModelPrefix, client); string modelId = await GetUniqueModelIdAsync(SamplesConstants.TemporaryModelPrefix, client); string twinId = await GetUniqueTwinIdAsync(SamplesConstants.TemporaryTwinPrefix, client); string newComponentModelPayload = SamplesConstants.TemporaryComponentModelPayload .Replace(SamplesConstants.ComponentId, componentModelId); string newModelPayload = SamplesConstants.TemporaryModelWithComponentPayload .Replace(SamplesConstants.ModelId, modelId) .Replace(SamplesConstants.ComponentId, componentModelId); // Then we create the models. await client .CreateModelsAsync(new[] { newComponentModelPayload, newModelPayload }); Console.WriteLine($"Successfully created models '{componentModelId}' and '{modelId}'"); // Create digital twin with Component payload. string twinPayload = SamplesConstants.TemporaryTwinPayload .Replace(SamplesConstants.ModelId, modelId); await client.CreateDigitalTwinAsync(twinId, twinPayload); Console.WriteLine($"Created digital twin '{twinId}'."); try { #region Snippet:DigitalTwinsSamplePublishTelemetry // construct your json telemetry payload by hand. await client.PublishTelemetryAsync(twinId, "{\"Telemetry1\": 5}"); Console.WriteLine($"Published telemetry message to twin '{twinId}'."); #endregion Snippet:DigitalTwinsSamplePublishTelemetry #region Snippet:DigitalTwinsSamplePublishComponentTelemetry // construct your json telemetry payload by serializing a dictionary. var telemetryPayload = new Dictionary <string, int> { { "ComponentTelemetry1", 9 } }; await client.PublishComponentTelemetryAsync( twinId, "Component1", JsonSerializer.Serialize(telemetryPayload)); Console.WriteLine($"Published component telemetry message to twin '{twinId}'."); #endregion Snippet:DigitalTwinsSamplePublishComponentTelemetry } catch (Exception ex) { FatalError($"Failed to publish a telemetry message due to: {ex.Message}"); } try { // Delete the twin. await client.DeleteDigitalTwinAsync(twinId); // Delete the models. await client.DeleteModelAsync(modelId); await client.DeleteModelAsync(componentModelId); } catch (RequestFailedException ex) when(ex.Status == (int)HttpStatusCode.NotFound) { // Digital twin or models do not exist. } catch (RequestFailedException ex) { FatalError($"Failed to delete due to: {ex.Message}"); } }
public async Task CreateHouseTwin() { try { List <string> dtdlList = ParseDTDLModels(); Response <ModelData[]> res = await _client.CreateModelsAsync(dtdlList); Console.WriteLine($"Model(s) created successfully!"); } catch (RequestFailedException e) { Console.WriteLine($"Response {e.Status}: {e.Message}"); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } var metaData = new Dictionary <string, object>() { { "$model", "dtmi:demo:House;1" }, { "$kind", "DigitalTwin" } }; var twinData = new Dictionary <string, object>() { { "$metadata", metaData }, { "ConstructionYear", "1985" }, { "Owner", "Glenn Colpaert" } }; await _client.CreateDigitalTwinAsync("127.0.0.1", JsonSerializer.Serialize(twinData)); Console.WriteLine($"Localhost Twin created successfully!"); metaData = new Dictionary <string, object>() { { "$model", "dtmi:demo:Floor;1" }, { "$kind", "DigitalTwin" } }; twinData = new Dictionary <string, object>() { { "$metadata", metaData } }; await _client.CreateDigitalTwinAsync("Floor1", JsonSerializer.Serialize(twinData)); Console.WriteLine($"Floor1 Twin created successfully!"); await _client.CreateDigitalTwinAsync("Floor2", JsonSerializer.Serialize(twinData)); Console.WriteLine($"Floor2 Twin created successfully!"); await _client.CreateDigitalTwinAsync("Floor3", JsonSerializer.Serialize(twinData)); Console.WriteLine($"Floor3 Twin created successfully!"); metaData = new Dictionary <string, object>() { { "$model", "dtmi:demo:Room;1" }, { "$kind", "DigitalTwin" } }; twinData = new Dictionary <string, object>() { { "$metadata", metaData } }; await _client.CreateDigitalTwinAsync("Kitchen", JsonSerializer.Serialize(twinData)); Console.WriteLine($"Kitchen Twin created successfully!"); await _client.CreateDigitalTwinAsync("LivingRoom", JsonSerializer.Serialize(twinData)); Console.WriteLine($"LivingRoom Twin created successfully!"); await _client.CreateDigitalTwinAsync("Bedroom1", JsonSerializer.Serialize(twinData)); Console.WriteLine($"Bedroom1 Twin created successfully!"); await _client.CreateDigitalTwinAsync("Bedroom2", JsonSerializer.Serialize(twinData)); Console.WriteLine($"Bedroom2 Twin created successfully!"); await _client.CreateDigitalTwinAsync("Bathroom", JsonSerializer.Serialize(twinData)); Console.WriteLine($"Bathroom Twin created successfully!"); await _client.CreateDigitalTwinAsync("MasterBedroom", JsonSerializer.Serialize(twinData)); Console.WriteLine($"MasterBedroom Twin created successfully!"); metaData = new Dictionary <string, object>() { { "$model", "dtmi:demo:Sensor;1" }, { "$kind", "DigitalTwin" } }; //Yes you have to initialize Temp and Hum as default //Unless you do an add (instead of replace) as update operation to the query interface. twinData = new Dictionary <string, object>() { { "$metadata", metaData }, { "FirmwareVersion", "2020.ADT.5782.3" } //, // { "Temperature", 0 }, // { "Humidity", 0}, }; await _client.CreateDigitalTwinAsync("TStat001", JsonSerializer.Serialize(twinData)); Console.WriteLine($"TStat001 Twin created successfully!"); await _client.CreateDigitalTwinAsync("TStat002", JsonSerializer.Serialize(twinData)); Console.WriteLine($"TStat002 Twin created successfully!"); await _client.CreateDigitalTwinAsync("TStat003", JsonSerializer.Serialize(twinData)); Console.WriteLine($"TStat003 Twin created successfully!"); await _client.CreateDigitalTwinAsync("TStat004", JsonSerializer.Serialize(twinData)); Console.WriteLine($"TStat004 Twin created successfully!"); await _client.CreateDigitalTwinAsync("TStat005", JsonSerializer.Serialize(twinData)); Console.WriteLine($"TStat005 Twin created successfully!"); var body = new Dictionary <string, object>() { { "$targetId", "Floor1" }, { "$relationshipName", "floors" } }; await _client.CreateRelationshipAsync("127.0.0.1", "localhost_to_Floor1", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship localhost_to_Floor1 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "Floor2" }, { "$relationshipName", "floors" } }; await _client.CreateRelationshipAsync("127.0.0.1", "localhost_to_floor2", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship localhost_to_floor2 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "Floor3" }, { "$relationshipName", "floors" } }; await _client.CreateRelationshipAsync("127.0.0.1", "localhost_to_floor3", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship localhost_to_floor3 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "Kitchen" }, { "$relationshipName", "rooms" } }; await _client.CreateRelationshipAsync("Floor1", "Floor1_to_kitchen", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship Floor1_to_kitchen created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "LivingRoom" }, { "$relationshipName", "rooms" } }; await _client.CreateRelationshipAsync("Floor1", "Floor1_to_livingroom", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship Floor1_to_livingroom created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "Bathroom" }, { "$relationshipName", "rooms" } }; await _client.CreateRelationshipAsync("Floor2", "floor2_to_bathroom", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship floor2_to_bathroom created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "Bedroom1" }, { "$relationshipName", "rooms" } }; await _client.CreateRelationshipAsync("Floor2", "floor2_to_bedroom1", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship floor2_to_bedroom1 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "Bedroom2" }, { "$relationshipName", "rooms" } }; await _client.CreateRelationshipAsync("Floor2", "floor2_to_bedroom2", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship floor2_to_bedroom2 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "MasterBedroom" }, { "$relationshipName", "rooms" } }; await _client.CreateRelationshipAsync("Floor3", "floor3_to_masterbedroom", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship floor3_to_masterbedroom created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "TStat001" }, { "$relationshipName", "sensors" } }; await _client.CreateRelationshipAsync("Kitchen", "kitchen_to_tstat001", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship kitchen_to_tstat001 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "TStat001" }, { "$relationshipName", "sensors" } }; await _client.CreateRelationshipAsync("LivingRoom", "livingroom_to_tstat001", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship LivingRoom_to_tstat001 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "TStat002" }, { "$relationshipName", "sensors" } }; await _client.CreateRelationshipAsync("Bedroom1", "bedroom_to_tstat002", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship bedroom_to_tstat002 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "TStat003" }, { "$relationshipName", "sensors" } }; await _client.CreateRelationshipAsync("Bedroom2", "bedroom2_to_tstat003", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship bedroom2_to_tstat003 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "TStat004" }, { "$relationshipName", "sensors" } }; await _client.CreateRelationshipAsync("Bathroom", "bathroom_to_tstat004", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship bathroom_to_tstat004 created successfully!"); body = new Dictionary <string, object>() { { "$targetId", "TStat005" }, { "$relationshipName", "sensors" } }; await _client.CreateRelationshipAsync("MasterBedroom", "masterbedroom_to_tstat005", JsonSerializer.Serialize(body)); Console.WriteLine($"Relationship masterbedroom_to_tstat005 created successfully!"); }
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 client.CreateModelsAsync(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.CreateDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false); } string queryString = "SELECT * FROM digitaltwins"; // act var options = new QueryOptions(); options.MaxItemsPerPage = pageSize; 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 <string> asyncPageableResponse = client.QueryAsync(queryString, null, queryTimeoutCancellationToken.Token); int count = 0; await foreach (Page <string> queriedTwinPage in asyncPageableResponse.AsPages()) { 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 <string> page in client.QueryAsync(queryString, options).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}"); } } }