コード例 #1
0
        public static async Task Run([IoTHubTrigger("messages/events", Connection = "IoTNorth")] EventData message, ILogger log)
        {
            string body = Encoding.UTF8.GetString(message.Body.Array);

            log.LogInformation($"C# IoT Hub trigger function processed a message: {body}");
            var powerMeterPayload = JsonSerializer.Deserialize <PowerMeter>(body);

            log.LogInformation($"The powerMeter has some value {powerMeterPayload.Consumption}");

            //what device sent this?
            log.LogInformation($"Some app level properties: {string.Join(',', message.Properties.Select(p=> $"{p.Key}:{p.Value}"))}");
            log.LogInformation($"Some system properties: {string.Join(',', message.SystemProperties.Select(p=> $"{p.Key}:{p.Value}"))}");

            log.LogInformation("********************************************************************************************************************************");
            log.LogInformation($"We can rely on the value of this property EventData.SystemProperties['iothub-connection-device-id']: {message.SystemProperties["iothub-connection-device-id"]}");
            log.LogInformation("********************************************************************************************************************************");
            var powerMeterId = (string)message.SystemProperties["iothub-connection-device-id"];

            // what do we do about Semantic Versions?

            // do we want to do something about updating average values?

            // let's just get the Digital Twin to do all that for us
            var dtClient = GetTwinClient("https://iotnorth-twin.api.uks.digitaltwins.azure.net");
            var updateDigitalTwinData = new JsonPatchDocument();

            updateDigitalTwinData.AppendReplace("/importPower", powerMeterPayload.Consumption);
            updateDigitalTwinData.AppendReplace("/timestamp", DateTime.UtcNow.ToString("u"));
            await dtClient.UpdateDigitalTwinAsync(powerMeterId, updateDigitalTwinData);

            // this trivial approach to properties is incorrect, we should be using telemetry to enable downstream consumers
            await dtClient.PublishTelemetryAsync(powerMeterId, Guid.NewGuid().ToString(), body);
        }
コード例 #2
0
        public async void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log)
        {
            // After this is deployed, you need to turn the Managed Identity Status to "On",
            // Grab Object Id of the function and assigned "Azure Digital Twins Owner (Preview)" role
            // to this function identity in order for this function to be authorized on ADT APIs.

            //Authenticate with Digital Twins
            var credentials           = new DefaultAzureCredential();
            DigitalTwinsClient client = new DigitalTwinsClient(
                new Uri(adtServiceUrl), credentials, new DigitalTwinsClientOptions
            {
                Transport = new HttpClientTransport(httpClient)
            });

            log.LogInformation($"ADT service client connection created.");

            if (eventGridEvent != null && eventGridEvent.Data != null)
            {
                log.LogInformation(eventGridEvent.Data.ToString());

                // Reading deviceId and temperature for IoT Hub JSON
                JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString());
                string  deviceId      = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"];
                var     temperature   = deviceMessage["body"]["Temperature"];

                log.LogInformation($"Device:{deviceId} Temperature is:{temperature}");

                //Update twin using device temperature
                var updateTwinData = new JsonPatchDocument();
                updateTwinData.AppendReplace("/Temperature", temperature.Value <double>());
                await client.UpdateDigitalTwinAsync(deviceId, updateTwinData);
            }
        }
コード例 #3
0
        public void ReplaceIsSerializedCorrectly()
        {
            JsonPatchDocument document = new JsonPatchDocument();

            document.AppendReplace("/a/b/c", "[ \"foo\", \"bar\" ]");
            Assert.AreEqual(document.ToString(), "[{\"op\":\"replace\",\"path\":\"/a/b/c\",\"value\":[\"foo\",\"bar\"]}]");
        }
        public static async Task Run(
            [EventHubTrigger("deviceevents", Connection = "EVENTHUB_CONNECTIONSTRING")] EventData[] events, ILogger log)
        {
            // After this is deployed, you need to turn the Managed Identity Status to "On",
            // Grab Object Id of the function and assigned "Azure Digital Twins Owner (Preview)" role
            // to this function identity in order for this function to be authorized on ADT APIs.
            if (adtInstanceUrl == null)
            {
                log.LogError("Application setting \"ADT_SERVICE_URL\" not set");
            }

            var exceptions = new List <Exception>();

            foreach (EventData eventData in events)
            {
                try
                {
                    // Get message body
                    string messageBody = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);

                    // 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)
                    });

                    // Reading Device ID from message headers
                    JObject jbody    = (JObject)JsonConvert.DeserializeObject(messageBody);
                    string  deviceId = eventData.SystemProperties["iothub-connection-device-id"].ToString();

                    string dtId = deviceId; // simple mapping

                    // Extracting temperature from device telemetry
                    double temperature = Convert.ToDouble(jbody["Temperature"].ToString());

                    // Update device Temperature property
                    var updateTwinData = new JsonPatchDocument();
                    updateTwinData.AppendReplace("/Temperature", temperature);
                    await client.UpdateDigitalTwinAsync(dtId, updateTwinData);

                    log.LogInformation($"Updated Temperature of device Twin '{dtId}' to: {temperature}");
                }
                catch (Exception e)
                {
                    // We need to keep processing the rest of the batch - capture this exception and continue.
                    exceptions.Add(e);
                }
            }

            if (exceptions.Count > 1)
            {
                throw new AggregateException(exceptions);
            }

            if (exceptions.Count == 1)
            {
                throw exceptions.Single();
            }
        }
        public static async Task Run(
            [EventHubTrigger("deviceevents", Connection = "EVENTHUB_CONNECTIONSTRING")] EventData[] events, ILogger log)
        {
            var exceptions = new List <Exception>(events.Length);

            // Create Digital Twin client
            var cred   = new ManagedIdentityCredential(adtAppId);
            var client = new DigitalTwinsClient(
                new Uri(adtInstanceUrl),
                cred,
                new DigitalTwinsClientOptions
            {
                Transport = new HttpClientTransport(singletonHttpClientInstance)
            });

            foreach (EventData eventData in events)
            {
                try
                {
                    log.LogDebug($"EventData: {System.Text.Json.JsonSerializer.Serialize(eventData)}");

                    // Get message body
                    string messageBody = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);

                    // Reading Device ID from message headers
                    JObject jbody    = (JObject)JsonConvert.DeserializeObject(messageBody);
                    string  deviceId = eventData.SystemProperties["iothub-connection-device-id"].ToString();

                    // Extracting temperature from device telemetry
                    double temperature = Convert.ToDouble(jbody["Temperature"].ToString());

                    // Update device Temperature property
                    var updateTwinData = new JsonPatchDocument();
                    updateTwinData.AppendReplace("/Temperature", temperature);
                    await client.UpdateDigitalTwinAsync(deviceId, updateTwinData);

                    log.LogInformation($"Updated Temperature of device Twin {deviceId} to: {temperature}");
                }
                catch (Exception e)
                {
                    // We need to keep processing the rest of the batch - capture this exception and continue.
                    exceptions.Add(e);
                }
            }

            if (exceptions.Count > 1)
            {
                throw new AggregateException(exceptions);
            }

            if (exceptions.Count == 1)
            {
                throw exceptions.Single();
            }
        }
コード例 #6
0
 private async Task UpdateTwinPropertAsync(string twinId, string propertyPath, object value)
 {
     try
     {
         var patch = new JsonPatchDocument();
         patch.AppendReplace(propertyPath, value);
         await _client.UpdateDigitalTwinAsync(twinId, patch);
     }
     catch (RequestFailedException exc)
     {
         _logger.LogError($"*** Error:{exc.Status}/{exc.Message}");
     }
 }
コード例 #7
0
        public static async Task UpdateTwinPropertyAsync(DigitalTwinsClient client, string twinId, string propertyPath, object value, ILogger log)
        {
            // If the twin does not exist, this will log an error
            try
            {
                var updateTwinData = new JsonPatchDocument();
                updateTwinData.AppendReplace(propertyPath, value);

                log.LogInformation($"UpdateTwinPropertyAsync sending {updateTwinData}");
                await client.UpdateDigitalTwinAsync(twinId, updateTwinData);
            }
            catch (RequestFailedException exc)
            {
                log.LogInformation($"*** Error:{exc.Status}/{exc.Message}");
            }
        }
コード例 #8
0
        public async void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log)
        {
            if (adtInstanceUrl == null)
            {
                log.LogError("Application setting \"ADT_SERVICE_URL\" not set");
            }

            try
            {
                // Authenticate with Digital Twins
                var cred   = new ManagedIdentityCredential("https://digitaltwins.azure.net");
                var client = new DigitalTwinsClient(
                    new Uri(adtInstanceUrl),
                    cred,
                    new DigitalTwinsClientOptions {
                    Transport = new HttpClientTransport(httpClient)
                });
                log.LogInformation($"ADT service client connection created.");

                if (eventGridEvent != null && eventGridEvent.Data != null)
                {
                    log.LogInformation(eventGridEvent.Data.ToString());

                    // <Find_device_ID_and_temperature>
                    JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString());
                    string  deviceId      = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"];
                    var     temperature   = deviceMessage["body"]["Temperature"];
                    // </Find_device_ID_and_temperature>

                    log.LogInformation($"Device:{deviceId} Temperature is:{temperature}");

                    // <Update_twin_with_device_temperature>
                    var updateTwinData = new JsonPatchDocument();
                    updateTwinData.AppendReplace("/Temperature", temperature.Value <double>());
                    await client.UpdateDigitalTwinAsync(deviceId, updateTwinData);

                    // </Update_twin_with_device_temperature>
                }
            }
            catch (Exception ex)
            {
                log.LogError($"Error in ingest function: {ex.Message}");
            }
        }
コード例 #9
0
        public void MultipleOperationsSerializedInOrder()
        {
            JsonPatchDocument document = new JsonPatchDocument();

            document.AppendTest("/a/b/c", "\"foo\"");
            document.AppendAdd("/a/b/c", "42");
            document.AppendReplace("/a/b/c", "[ \"foo\", \"bar\" ]");
            document.AppendRemove("/a/b/c");
            document.AppendMove("/a/b/c", "/a/b/d");
            document.AppendCopy("/a/b/c", "/a/b/d");

            Assert.AreEqual(document.ToString(),
                            "[" +
                            "{\"op\":\"test\",\"path\":\"/a/b/c\",\"value\":\"foo\"}," +
                            "{\"op\":\"add\",\"path\":\"/a/b/c\",\"value\":42}," +
                            "{\"op\":\"replace\",\"path\":\"/a/b/c\",\"value\":[\"foo\",\"bar\"]}," +
                            "{\"op\":\"remove\",\"path\":\"/a/b/c\"}," +
                            "{\"op\":\"move\",\"from\":\"/a/b/c\",\"path\":\"/a/b/d\"}," +
                            "{\"op\":\"copy\",\"from\":\"/a/b/c\",\"path\":\"/a/b/d\"}" +
                            "]");
        }
コード例 #10
0
        public static async Task Run([IoTHubTrigger("messages/events", Connection = "IoTHubBuiltInConnection", ConsumerGroup = "function")] EventData message, ILogger log)
        {
            DigitalTwinsClient client;

            try
            {
                //Authenticate with Digital Twins
                var credentials = new DefaultAzureCredential();
                client = new DigitalTwinsClient(
                    new Uri(adtServiceUrl),
                    credentials,
                    new DigitalTwinsClientOptions {
                    Transport = new HttpClientTransport(httpClient)
                }
                    );

                log.LogInformation($"ADT service client connection created.");
            }
            catch (Exception e)
            {
                log.LogError($"ADT service client connection failed. {e}");
                return;
            }

            if (client != null)
            {
                if (message != null && message.Body != null)
                {
                    var msg = Encoding.UTF8.GetString(message.Body.Array);
                    log.LogInformation($"C# IoT Hub trigger function processed a message: {msg}");

                    // Get device Id
                    string deviceId = (string)message.SystemProperties["iothub-connection-device-id"];

                    try
                    {
                        var sensordata = JsonConvert.DeserializeObject <SensorMessage>(msg);

                        JsonPatchDocument updateTwinData = new JsonPatchDocument();
                        updateTwinData.AppendReplace <string>("/Name", sensordata.SensorName);
                        updateTwinData.AppendReplace <float>("/Value", (float)sensordata.SensorValue);

                        await client.UpdateDigitalTwinAsync(deviceId, updateTwinData);   //deviceId == dtid
                    }
                    catch (JsonException jex)
                    {
                        log.LogError("Message parsing error.", jex);
                    }
                    catch (RequestFailedException exc)
                    {
                        log.LogInformation($"{deviceId}*** Error:{exc.Status}/{exc.Message}");

                        // 최초 Update 할 경우 Replace를 쓰면 오류발생. Add를 써야함.
                        var sensordata = JsonConvert.DeserializeObject <SensorMessage>(msg);

                        JsonPatchDocument addTwinData = new JsonPatchDocument();
                        addTwinData.AppendAdd <string>("/Name", sensordata.SensorName);
                        addTwinData.AppendAdd <float>("/Value", (float)sensordata.SensorValue);

                        await client.UpdateDigitalTwinAsync(deviceId, addTwinData);
                    }
                    catch (Exception ex)
                    {
                        log.LogError("Update Twin error.", ex);
                    }
                }
            }
        }
コード例 #11
0
        public async void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log)
        {
            try
            {
                // After this is deployed, you need to turn the Managed Identity Status to "On",
                // Grab Object Id of the function and assigned "Azure Digital Twins Owner (Preview)" role
                // to this function identity in order for this function to be authorized on ADT APIs.
                //Authenticate with Digital Twins
                var credentials = new DefaultAzureCredential();
                log.LogInformation(credentials.ToString());
                DigitalTwinsClient client = new DigitalTwinsClient(
                    new Uri(adtServiceUrl), credentials, new DigitalTwinsClientOptions
                {
                    Transport = new HttpClientTransport(httpClient)
                });
                log.LogInformation($"ADT service client connection created.");
                if (eventGridEvent.Data.ToString().Contains("Alert"))
                {
                    JObject alertMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString());
                    string  deviceId     = (string)alertMessage["systemProperties"]["iothub-connection-device-id"];
                    var     ID           = alertMessage["body"]["TurbineID"];
                    var     alert        = alertMessage["body"]["Alert"];
                    log.LogInformation($"Device:{deviceId} Device Id is:{ID}");
                    log.LogInformation($"Device:{deviceId} Alert Status is:{alert}");

                    var updateProperty = new JsonPatchDocument();
                    updateProperty.AppendReplace("/Alert", alert.Value <bool>());
                    updateProperty.AppendReplace("/TurbineID", ID.Value <string>());
                    log.LogInformation(updateProperty.ToString());
                    try
                    {
                        await client.UpdateDigitalTwinAsync(deviceId, updateProperty);
                    }
                    catch (Exception e)
                    {
                        log.LogInformation(e.Message);
                    }
                }
                else if (eventGridEvent != null && eventGridEvent.Data != null)
                {
                    JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString());
                    string  deviceId      = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"];
                    var     ID            = deviceMessage["body"]["TurbineID"];
                    var     TimeInterval  = deviceMessage["body"]["TimeInterval"];
                    var     Description   = deviceMessage["body"]["Description"];
                    var     Code          = deviceMessage["body"]["Code"];
                    var     WindSpeed     = deviceMessage["body"]["WindSpeed"];
                    var     Ambient       = deviceMessage["body"]["Ambient"];
                    var     Rotor         = deviceMessage["body"]["Rotor"];
                    var     Power         = deviceMessage["body"]["Power"];

                    log.LogInformation($"Device:{deviceId} Device Id is:{ID}");
                    log.LogInformation($"Device:{deviceId} Time interval is:{TimeInterval}");
                    log.LogInformation($"Device:{deviceId} Description is:{Description}");
                    log.LogInformation($"Device:{deviceId} CodeNumber is:{Code}");
                    log.LogInformation($"Device:{deviceId} WindSpeed is:{WindSpeed}");
                    log.LogInformation($"Device:{deviceId} Ambient Temperature is:{Ambient}");
                    log.LogInformation($"Device:{deviceId} Rotor RPM is:{Rotor}");
                    log.LogInformation($"Device:{deviceId} Power is:{Power}");
                    var updateProperty   = new JsonPatchDocument();
                    var turbineTelemetry = new Dictionary <string, Object>()
                    {
                        ["TurbineID"]    = ID,
                        ["TimeInterval"] = TimeInterval,
                        ["Description"]  = Description,
                        ["Code"]         = Code,
                        ["WindSpeed"]    = WindSpeed,
                        ["Ambient"]      = Ambient,
                        ["Rotor"]        = Rotor,
                        ["Power"]        = Power
                    };
                    updateProperty.AppendAdd("/TurbineID", ID.Value <string>());

                    log.LogInformation(updateProperty.ToString());
                    try
                    {
                        await client.PublishTelemetryAsync(deviceId, Guid.NewGuid().ToString(), JsonConvert.SerializeObject(turbineTelemetry));
                    }
                    catch (Exception e)
                    {
                        log.LogInformation(e.Message);
                    }
                }
            }
            catch (Exception e)
            {
                log.LogInformation(e.Message);
            }
        }
コード例 #12
0
        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.CreateOrReplaceDigitalTwinAsync <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}");
                }
            }
        }
コード例 #13
0
        public async Task DigitalTwins_DeleteTwinFailsIfMatchProvidesOutdatedEtag()
        {
            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.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false);

                // get twin
                ETag?etagBeforeUpdate = (await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomTwinId).ConfigureAwait(false)).Value.ETag;

                // update twin
                JsonPatchDocument updateTwinPatchDocument = new JsonPatchDocument();
                updateTwinPatchDocument.AppendAdd("/Humidity", 30);
                updateTwinPatchDocument.AppendReplace("/Temperature", 70);
                updateTwinPatchDocument.AppendRemove("/EmployeeId");

                await client.UpdateDigitalTwinAsync(roomTwinId, updateTwinPatchDocument, ETag.All).ConfigureAwait(false);

                // assert
                Func <Task> act = async() =>
                {
                    // since the ETag is out of date, this call should throw a 412
                    await client.DeleteDigitalTwinAsync(roomTwinId, etagBeforeUpdate).ConfigureAwait(false);
                };

                act.Should().Throw <RequestFailedException>()
                .And.Status.Should().Be((int)HttpStatusCode.PreconditionFailed);
            }
            finally
            {
                // cleanup
                try
                {
                    if (!string.IsNullOrWhiteSpace(roomModelId))
                    {
                        await client.DeleteModelAsync(roomModelId).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    Assert.Fail($"Test clean up failed: {ex.Message}");
                }
            }
        }
コード例 #14
0
        public async Task DigitalTwins_DeleteTwinSucceedsIfMatchProvidesCorrectEtag()
        {
            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.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false);

                // update twin
                JsonPatchDocument updateTwinPatchDocument = new JsonPatchDocument();
                updateTwinPatchDocument.AppendAdd("/Humidity", 30);
                updateTwinPatchDocument.AppendReplace("/Temperature", 70);
                updateTwinPatchDocument.AppendRemove("/EmployeeId");
                await client.UpdateDigitalTwinAsync(roomTwinId, updateTwinPatchDocument, ETag.All).ConfigureAwait(false);

                // get twin
                ETag?correctETag = (await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomTwinId).ConfigureAwait(false)).Value.ETag;
                Assert.IsNotNull(correctETag);

                try
                {
                    // since the ETag is not out of date, this call should not throw a 412
                    await client.DeleteDigitalTwinAsync(roomTwinId, correctETag).ConfigureAwait(false);
                }
                catch (RequestFailedException ex) when(ex.Status == (int)HttpStatusCode.PreconditionFailed)
                {
                    throw new AssertionException("UpdateRelationship should not have thrown PreconditionFailed because the ETag was up to date", ex);
                }
            }
            finally
            {
                // cleanup
                try
                {
                    if (!string.IsNullOrWhiteSpace(roomModelId))
                    {
                        await client.DeleteModelAsync(roomModelId).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    Assert.Fail($"Test clean up failed: {ex.Message}");
                }
            }
        }
コード例 #15
0
        public async Task DigitalTwins_PatchTwinFailsIfInvalidETagProvided()
        {
            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.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false);

                // get twin
                ETag?etagBeforeUpdate = (await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomTwinId).ConfigureAwait(false)).Value.ETag;

                Assert.IsNotNull(etagBeforeUpdate);

                // update twin once to make the previous etag fall out of date
                JsonPatchDocument updateTwinPatchDocument = new JsonPatchDocument();
                updateTwinPatchDocument.AppendAdd("/Humidity", 30);
                updateTwinPatchDocument.AppendReplace("/Temperature", 70);
                updateTwinPatchDocument.AppendRemove("/EmployeeId");
                await client.UpdateDigitalTwinAsync(roomTwinId, updateTwinPatchDocument, ETag.All).ConfigureAwait(false);

                // update twin again, but with an out of date etag, which should cause a 412 from service
                JsonPatchDocument secondUpdateTwinPatchDocument = new JsonPatchDocument();
                secondUpdateTwinPatchDocument.AppendReplace("/Humidity", 80);
                Func <Task> act = async() =>
                {
                    await client.UpdateDigitalTwinAsync(roomTwinId, secondUpdateTwinPatchDocument, etagBeforeUpdate).ConfigureAwait(false);
                };

                act.Should().Throw <RequestFailedException>()
                .And.Status.Should().Be((int)HttpStatusCode.PreconditionFailed);
            }
            finally
            {
                // cleanup
                try
                {
                    if (!string.IsNullOrWhiteSpace(roomModelId))
                    {
                        await client.DeleteModelAsync(roomModelId).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    Assert.Fail($"Test clean up failed: {ex.Message}");
                }
            }
        }
コード例 #16
0
        public async Task Component_UpdateComponentFailsWhenIfMatchHeaderOutOfDate()
        {
            // arrange

            DigitalTwinsClient client = GetClient();

            string wifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.WifiModelIdPrefix).ConfigureAwait(false);

            string roomWithWifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomWithWifiModelIdPrefix).ConfigureAwait(false);

            string roomWithWifiTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.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 CreateAndListModelsAsync(client, new List <string> {
                    roomWithWifiModel, wifiModel
                }).ConfigureAwait(false);

                // create room digital twin
                BasicDigitalTwin roomWithWifiTwin = TestAssetsHelper.GetRoomWithWifiTwinPayload(roomWithWifiModelId, wifiComponentName);
                await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId, roomWithWifiTwin);

                // Get the component
                Response <object> getComponentResponse = await client
                                                         .GetComponentAsync <object>(
                    roomWithWifiTwinId,
                    wifiComponentName)
                                                         .ConfigureAwait(false);

                ETag?etagBeforeUpdate = (await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId)).Value.ETag;

                // Patch component
                JsonPatchDocument componentUpdatePatchDocument = new JsonPatchDocument();
                componentUpdatePatchDocument.AppendReplace("/Network", "New Network");

                Response updateComponentResponse = await client
                                                   .UpdateComponentAsync(
                    roomWithWifiTwinId,
                    wifiComponentName,
                    componentUpdatePatchDocument)
                                                   .ConfigureAwait(false);

                // Patch component again, but with the now out of date ETag
                JsonPatchDocument secondComponentUpdatePatchDocument = new JsonPatchDocument();
                secondComponentUpdatePatchDocument.AppendReplace("/Network", "Even newer Network");

                Func <Task> act = async() =>
                {
                    await client
                    .UpdateComponentAsync(
                        roomWithWifiTwinId,
                        wifiComponentName,
                        secondComponentUpdatePatchDocument,
                        etagBeforeUpdate)
                    .ConfigureAwait(false);
                };

                act.Should().Throw <RequestFailedException>()
                .And.Status.Should().Be((int)HttpStatusCode.PreconditionFailed);
            }
            catch (Exception ex)
            {
                Assert.Fail($"Failure in executing a step in the test case: {ex.Message}.");
            }
            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}");
                }
            }
        }
コード例 #17
0
        public async Task Component_UpdateComponentSucceedsWhenIfMatchHeaderIsCorrect()
        {
            // arrange

            DigitalTwinsClient client = GetClient();

            string wifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.WifiModelIdPrefix).ConfigureAwait(false);

            string roomWithWifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomWithWifiModelIdPrefix).ConfigureAwait(false);

            string roomWithWifiTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.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
                BasicDigitalTwin roomWithWifiTwin = TestAssetsHelper.GetRoomWithWifiTwinPayload(roomWithWifiModelId, wifiComponentName);
                await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId, roomWithWifiTwin);

                // Get the component
                Response <object> getComponentResponse = await client
                                                         .GetComponentAsync <object>(
                    roomWithWifiTwinId,
                    wifiComponentName)
                                                         .ConfigureAwait(false);

                // Patch component
                JsonPatchDocument componentUpdatePatchDocument = new JsonPatchDocument();
                componentUpdatePatchDocument.AppendReplace("/Network", "New Network");

                Response updateComponentResponse = await client
                                                   .UpdateComponentAsync(
                    roomWithWifiTwinId,
                    wifiComponentName,
                    componentUpdatePatchDocument)
                                                   .ConfigureAwait(false);

                // Get the latest ETag
                ETag?etagBeforeUpdate = (await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId)).Value.ETag;
                Assert.IsNotNull(etagBeforeUpdate);

                // Patch component again, but with the now out of date ETag
                JsonPatchDocument secondComponentUpdatePatchDocument = new JsonPatchDocument();
                componentUpdatePatchDocument.AppendReplace("/Network", "Even newer Network");

                try
                {
                    await client
                    .UpdateComponentAsync(
                        roomWithWifiTwinId,
                        wifiComponentName,
                        secondComponentUpdatePatchDocument,
                        etagBeforeUpdate)
                    .ConfigureAwait(false);
                }
                catch (RequestFailedException ex) when(ex.Status == (int)HttpStatusCode.PreconditionFailed)
                {
                    throw new AssertionException("UpdateComponent should not have thrown PreconditionFailed because the ETag was up to date", ex);
                }
            }
            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}");
                }
            }
        }
コード例 #18
0
        public async Task Component_Lifecycle()
        {
            // arrange

            DigitalTwinsClient client = GetClient();

            string wifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.WifiModelIdPrefix).ConfigureAwait(false);

            string roomWithWifiModelId = await GetUniqueModelIdAsync(client, TestAssetDefaults.RoomWithWifiModelIdPrefix).ConfigureAwait(false);

            string roomWithWifiTwinId = await GetUniqueTwinIdAsync(client, TestAssetDefaults.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
                BasicDigitalTwin roomWithWifiTwin = TestAssetsHelper.GetRoomWithWifiTwinPayload(roomWithWifiModelId, wifiComponentName);
                await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomWithWifiTwinId, roomWithWifiTwin);

                // Get the component
                Response <object> getComponentResponse = await client
                                                         .GetComponentAsync <object>(
                    roomWithWifiTwinId,
                    wifiComponentName)
                                                         .ConfigureAwait(false);

                // The response to the GET request should be 200 (OK)
                getComponentResponse.GetRawResponse().Status.Should().Be((int)HttpStatusCode.OK);

                // Patch component
                JsonPatchDocument componentUpdatePatchDocument = new JsonPatchDocument();
                componentUpdatePatchDocument.AppendReplace("/Network", "New Network");

                Response updateComponentResponse = await client
                                                   .UpdateComponentAsync(
                    roomWithWifiTwinId,
                    wifiComponentName,
                    componentUpdatePatchDocument)
                                                   .ConfigureAwait(false);

                // The response to the Patch request should be 204 (No content)
                updateComponentResponse.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}");
                }
            }
        }
コード例 #19
0
        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}");
                }
            }
        }
コード例 #20
0
        /// <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
            await client.CreateModelsAsync(
                new[]
            {
                newComponentModelPayload,
                newModelPayload
            });

            Console.WriteLine($"Created models {componentModelId} and {modelId}.");

            #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 },
                Contents =
                {
                    // digital twin properties
                    { "Prop1",          "Value1"            },
                    { "Prop2",                          987 },
                    // component
                    {
                        "Component1",
                        new BasicDigitalTwinComponent
                        {
                            // component properties
                            Contents =
                            {
                                { "ComponentProp1", "Component value 1" },
                                { "ComponentProp2",                 123 },
                            },
                        }
                    },
                },
            };

            Response <BasicDigitalTwin> createDigitalTwinResponse = await client.CreateOrReplaceDigitalTwinAsync(basicDtId, basicTwin);

            Console.WriteLine($"Created digital twin '{createDigitalTwinResponse.Value.Id}'.");

            #endregion Snippet:DigitalTwinsSampleCreateBasicTwin

            // You can also get a digital twin as a BasicDigitalTwin type.
            // 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 <BasicDigitalTwin> getBasicDtResponse = await client.GetDigitalTwinAsync <BasicDigitalTwin>(basicDtId);

            if (getBasicDtResponse.GetRawResponse().Status == (int)HttpStatusCode.OK)
            {
                BasicDigitalTwin basicDt = 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.Contents["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.Contents["Prop1"]}\n\t" +
                                  $"Prop2: {basicDt.Contents["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 MyCustomComponent
                {
                    ComponentProp1 = "Component prop1 val",
                    ComponentProp2 = 123,
                },
            };
            Response <CustomDigitalTwin> createCustomDigitalTwinResponse = await client.CreateOrReplaceDigitalTwinAsync(customDtId, customTwin);

            Console.WriteLine($"Created digital twin '{createCustomDigitalTwinResponse.Value.Id}'.");

            #endregion Snippet:DigitalTwinsSampleCreateCustomTwin

            // Getting a digital twin as a custom data type is extremely easy.
            // Custom types provide the best possible experience.

            #region Snippet:DigitalTwinsSampleGetCustomDigitalTwin

            Response <CustomDigitalTwin> getCustomDtResponse = await client.GetDigitalTwinAsync <CustomDigitalTwin>(customDtId);

            CustomDigitalTwin customDt = 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,
            // using an optional utility to build the payload.
            var componentJsonPatchDocument = new JsonPatchDocument();
            componentJsonPatchDocument.AppendReplace("/ComponentProp1", "Some new value");
            await client.UpdateComponentAsync(basicDtId, "Component1", componentJsonPatchDocument);

            Console.WriteLine($"Updated component for digital twin '{basicDtId}'.");

            #endregion Snippet:DigitalTwinsSampleUpdateComponent

            // Get Component

            #region Snippet:DigitalTwinsSampleGetComponent

            await client.GetComponentAsync <MyCustomComponent>(basicDtId, SamplesConstants.ComponentName);

            Console.WriteLine($"Retrieved component for digital twin '{basicDtId}'.");

            #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}");
            }
        }
コード例 #21
0
        public async Task DigitalTwins_PatchTwinSucceedsIfCorrectETagProvided()
        {
            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 CreateAndListModelsAsync(client, new List <string> {
                    roomModel
                }).ConfigureAwait(false);

                // act

                // create room twin
                BasicDigitalTwin roomTwin = TestAssetsHelper.GetRoomTwinPayload(roomModelId);
                await client.CreateOrReplaceDigitalTwinAsync <BasicDigitalTwin>(roomTwinId, roomTwin).ConfigureAwait(false);

                // update twin once
                JsonPatchDocument updateTwinPatchDocument = new JsonPatchDocument();
                updateTwinPatchDocument.AppendAdd("/Humidity", 30);
                updateTwinPatchDocument.AppendReplace("/Temperature", 70);
                updateTwinPatchDocument.AppendRemove("/EmployeeId");
                await client.UpdateDigitalTwinAsync(roomTwinId, updateTwinPatchDocument, ETag.All).ConfigureAwait(false);

                // get twin
                ETag?etagBeforeUpdate = (await client.GetDigitalTwinAsync <BasicDigitalTwin>(roomTwinId).ConfigureAwait(false)).Value.ETag;

                Assert.IsNotNull(etagBeforeUpdate);

                // update twin again, but with the correct etag
                JsonPatchDocument secondUpdateTwinPatchDocument = new JsonPatchDocument();
                secondUpdateTwinPatchDocument.AppendReplace("/Humidity", 80);
                try
                {
                    await client.UpdateDigitalTwinAsync(roomTwinId, secondUpdateTwinPatchDocument, etagBeforeUpdate).ConfigureAwait(false);
                }
                catch (RequestFailedException ex) when(ex.Status == (int)HttpStatusCode.PreconditionFailed)
                {
                    throw new AssertionException("UpdateDigitalTwin should not have thrown PreconditionFailed because the ETag was up to date", ex);
                }
            }
            catch (Exception ex)
            {
                Assert.Fail($"Failure in executing a step in the test case: {ex.Message}.");
            }
            finally
            {
                // cleanup
                try
                {
                    if (!string.IsNullOrWhiteSpace(roomModelId))
                    {
                        await client.DeleteModelAsync(roomModelId).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    Assert.Fail($"Test clean up failed: {ex.Message}");
                }
            }
        }