public async Task DigitalTwinClient_Http_TokenCredentialAuth_Success()
        {
            // arrange
            TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, _devicePrefix).ConfigureAwait(false);

            string thermostatModelId = "dtmi:com:example:TemperatureController;1";

            // Create a device client instance initializing it with the "Thermostat" model.
            var options = new ClientOptions
            {
                ModelId = thermostatModelId,
            };

            using DeviceClient deviceClient = testDevice.CreateDeviceClient(Client.TransportType.Mqtt, options);

            // Call openAsync() to open the device's connection, so that the ModelId is sent over Mqtt CONNECT packet.
            await deviceClient.OpenAsync().ConfigureAwait(false);

            using var digitalTwinClient = DigitalTwinClient.Create(
                      Configuration.IoTHub.GetIotHubHostName(),
                      Configuration.IoTHub.GetClientSecretCredential());

            // act
            HttpOperationResponse <ThermostatTwin, DigitalTwinGetHeaders> response = await digitalTwinClient
                                                                                     .GetDigitalTwinAsync <ThermostatTwin>(testDevice.Id)
                                                                                     .ConfigureAwait(false);

            ThermostatTwin twin = response.Body;

            // assert
            twin.Metadata.ModelId.Should().Be(thermostatModelId);

            // cleanup
            await testDevice.RemoveDeviceAsync().ConfigureAwait(false);
        }
        public async Task DigitalTwinWithOnlyRootComponentOperationsAsync()
        {
            // Create a new test device instance.
            TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, _devicePrefix).ConfigureAwait(false);

            string deviceId = testDevice.Id;

            try
            {
                // Create a device client instance over Mqtt, initializing it with the "Thermostat" model which has only a root component.
                var options = new ClientOptions
                {
                    ModelId = ThermostatModelId,
                };
                using DeviceClient deviceClient = testDevice.CreateDeviceClient(Client.TransportType.Mqtt, options);

                // Call openAsync() to open the device's connection, so that the ModelId is sent over Mqtt CONNECT packet.
                await deviceClient.OpenAsync().ConfigureAwait(false);

                // Perform operations on the digital twin.
                using var digitalTwinClient = DigitalTwinClient.CreateFromConnectionString(s_connectionString);

                // Retrieve the digital twin.
                HttpOperationResponse <ThermostatTwin, DigitalTwinGetHeaders> response =
                    await digitalTwinClient.GetDigitalTwinAsync <ThermostatTwin>(deviceId).ConfigureAwait(false);

                ThermostatTwin twin = response.Body;
                twin.Metadata.ModelId.Should().Be(ThermostatModelId);

                // Set callback handler for receiving root-level twin property updates.
                await deviceClient.SetDesiredPropertyUpdateCallbackAsync((patch, context) =>
                {
                    Logger.Trace($"{nameof(DigitalTwinWithComponentOperationsAsync)}: DesiredProperty update received: {patch}, {context}");
                    return(Task.FromResult(true));
                }, deviceClient);

                // Update the root-level property "targetTemperature".
                string propertyName  = "targetTemperature";
                double propertyValue = new Random().Next(0, 100);
                var    ops           = new UpdateOperationsUtility();
                ops.AppendAddPropertyOp($"/{propertyName}", propertyValue);
                string patch = ops.Serialize();
                HttpOperationHeaderResponse <DigitalTwinUpdateHeaders> updateResponse =
                    await digitalTwinClient.UpdateDigitalTwinAsync(deviceId, patch);

                updateResponse.Response.StatusCode.Should().Be(HttpStatusCode.Accepted);

                // Set callback to handle root-level command invocation request.
                int    expectedCommandStatus = 200;
                string commandName           = "getMaxMinReport";
                await deviceClient.SetMethodHandlerAsync(commandName,
                                                         (request, context) =>
                {
                    Logger.Trace($"{nameof(DigitalTwinWithOnlyRootComponentOperationsAsync)}: Digital twin command received: {request.Name}.");
                    string payload = JsonConvert.SerializeObject(request.Name);
                    return(Task.FromResult(new MethodResponse(Encoding.UTF8.GetBytes(payload), expectedCommandStatus)));
                },
                                                         null);

                // Invoke the root-level command "getMaxMinReport" on the digital twin.
                DateTimeOffset since   = DateTimeOffset.Now.Subtract(TimeSpan.FromMinutes(1));
                string         payload = JsonConvert.SerializeObject(since);
                HttpOperationResponse <DigitalTwinCommandResponse, DigitalTwinInvokeCommandHeaders> commandResponse =
                    await digitalTwinClient.InvokeCommandAsync(deviceId, commandName, payload).ConfigureAwait(false);

                commandResponse.Body.Status.Should().Be(expectedCommandStatus);
                commandResponse.Body.Payload.Should().Be(JsonConvert.SerializeObject(commandName));
            }
            finally
            {
                // Delete the device.
                await testDevice.RemoveDeviceAsync().ConfigureAwait(false);
            }
        }