Example #1
0
        public void UpdateUtilityAppendMultipleOperations()
        {
            var    op           = new UpdateOperationsUtility();
            string addPath      = "testPath1";
            int    addValue     = 10;
            string replacePath  = "testpath2";
            int    replaceValue = 20;

            op.AppendAddPropertyOp(addPath, addValue);
            op.AppendReplacePropertyOp(replacePath, replaceValue);
            string operations = op.Serialize();

            // There should be two operations added.
            var jArray = JArray.Parse(operations);

            jArray.Count.Should().Be(2);

            // The patch operation added should have an "add" and a "replace" operation.
            var expectedOperations = new List <string> {
                Add, Replace
            };
            var actualOperations = new List <string>();

            foreach (JObject item in jArray)
            {
                actualOperations.Add(item.Value <string>(Op));
            }
            actualOperations.Should().OnlyContain(item => expectedOperations.Contains(item));
        }
        private async Task UpdateDigitalTwinComponentPropertyAsync()
        {
            // Choose a random value to assign to the targetTemperature property in thermostat1 component
            int desiredTargetTemperature = Random.Next(0, 100);

            const string targetTemperaturePropertyName = "targetTemperature";
            var          updateOperation = new UpdateOperationsUtility();

            // First let's take a look at when the property was updated and what was it set to.
            HttpOperationResponse <TemperatureControllerTwin, DigitalTwinGetHeaders> getDigitalTwinResponse = await _digitalTwinClient
                                                                                                              .GetDigitalTwinAsync <TemperatureControllerTwin>(_digitalTwinId);

            ThermostatTwin thermostat1 = getDigitalTwinResponse.Body.Thermostat1;

            if (thermostat1 != null)
            {
                // Thermostat1 is present in the TemperatureController twin. We can add/replace the component-level property "targetTemperature"
                double?currentComponentTargetTemperature = getDigitalTwinResponse.Body.Thermostat1.TargetTemperature;
                if (currentComponentTargetTemperature != null)
                {
                    DateTimeOffset targetTemperatureDesiredLastUpdateTime = getDigitalTwinResponse.Body.Thermostat1.Metadata.TargetTemperature.LastUpdateTime;
                    _logger.LogDebug($"The property {targetTemperaturePropertyName} under component {Thermostat1Component} was last updated on `" +
                                     $"{targetTemperatureDesiredLastUpdateTime.ToLocalTime()} `" +
                                     $" with a value of {getDigitalTwinResponse.Body.Thermostat1.Metadata.TargetTemperature.DesiredValue}.");

                    // The property path to be replaced should be prepended with a '/'
                    updateOperation.AppendReplacePropertyOp($"/{Thermostat1Component}/{targetTemperaturePropertyName}", desiredTargetTemperature);
                }
                else
                {
                    _logger.LogDebug($"The property {targetTemperaturePropertyName} under component {Thermostat1Component} `" +
                                     $"was never set on the {_digitalTwinId} digital twin.");

                    // The property path to be added should be prepended with a '/'
                    updateOperation.AppendAddPropertyOp($"/{Thermostat1Component}/{targetTemperaturePropertyName}", desiredTargetTemperature);
                }
            }
            else
            {
                // Thermostat1 is not present in the TemperatureController twin. We will add the component
                var componentProperty = new Dictionary <string, object> {
                    { targetTemperaturePropertyName, desiredTargetTemperature }, { "$metadata", new object() }
                };
                _logger.LogDebug($"The component {Thermostat1Component} does not exist on the {_digitalTwinId} digital twin.");

                // The property path to be replaced should be prepended with a '/'
                updateOperation.AppendAddComponentOp($"/{Thermostat1Component}", componentProperty);
            }

            _logger.LogDebug($"Update the {targetTemperaturePropertyName} property under component {Thermostat1Component} on the {_digitalTwinId} `" +
                             $"digital twin to {desiredTargetTemperature}.");
            HttpOperationHeaderResponse <DigitalTwinUpdateHeaders> updateDigitalTwinResponse = await _digitalTwinClient
                                                                                               .UpdateDigitalTwinAsync(_digitalTwinId, updateOperation.Serialize());

            _logger.LogDebug($"Update {_digitalTwinId} digital twin response: {updateDigitalTwinResponse.Response.StatusCode}.");

            // Print the TemperatureController digital twin
            await GetAndPrintDigitalTwinAsync <TemperatureControllerTwin>();
        }
        private async Task UpdateCurrentTemperaturePropertyAsync()
        {
            // Choose a random value to assign to the currentTemperature property
            int currentTemperature = Random.Next(0, 100);

            const string currentTemperaturePropertyName = "currentTemperature";
            var          updateOperation = new UpdateOperationsUtility();

            // First, add the property to the digital twin
            updateOperation.AppendAddPropertyOp($"/{currentTemperaturePropertyName}", currentTemperature);
            _logger.LogDebug($"Add the {currentTemperaturePropertyName} property on the {_digitalTwinId} digital twin " +
                             $"with a value of {currentTemperature}.");
            HttpOperationHeaderResponse <DigitalTwinUpdateHeaders> addPropertyToDigitalTwinResponse = await _digitalTwinClient
                                                                                                      .UpdateDigitalTwinAsync(_digitalTwinId, updateOperation.Serialize());

            _logger.LogDebug($"Update {_digitalTwinId} digital twin response: {addPropertyToDigitalTwinResponse.Response.StatusCode}.");

            // Print the Thermostat digital twin
            await GetAndPrintDigitalTwinAsync <ThermostatTwin>();

            // Second, replace the property to a different value
            int newCurrentTemperature = Random.Next(0, 100);

            updateOperation.AppendReplacePropertyOp($"/{currentTemperaturePropertyName}", newCurrentTemperature);
            _logger.LogDebug($"Replace the {currentTemperaturePropertyName} property on the {_digitalTwinId} digital twin " +
                             $"with a value of {newCurrentTemperature}.");
            HttpOperationHeaderResponse <DigitalTwinUpdateHeaders> replacePropertyInDigitalTwinResponse = await _digitalTwinClient
                                                                                                          .UpdateDigitalTwinAsync(_digitalTwinId, updateOperation.Serialize());

            _logger.LogDebug($"Update {_digitalTwinId} digital twin response: {replacePropertyInDigitalTwinResponse.Response.StatusCode}.");

            // Print the Thermostat digital twin
            await GetAndPrintDigitalTwinAsync <ThermostatTwin>();

            // Third, remove the currentTemperature property
            updateOperation.AppendRemoveOp($"/{currentTemperaturePropertyName}");
            _logger.LogDebug($"Remove the {currentTemperaturePropertyName} property on the {_digitalTwinId} digital twin.");
            HttpOperationHeaderResponse <DigitalTwinUpdateHeaders> removePropertyInDigitalTwinResponse = await _digitalTwinClient
                                                                                                         .UpdateDigitalTwinAsync(_digitalTwinId, updateOperation.Serialize());

            _logger.LogDebug($"Update {_digitalTwinId} digital twin response: {removePropertyInDigitalTwinResponse.Response.StatusCode}.");

            // Print the Thermostat digital twin
            await GetAndPrintDigitalTwinAsync <ThermostatTwin>();
        }
Example #4
0
        public void UpdateUtilityAppendsAddPropertyOp()
        {
            var    op    = new UpdateOperationsUtility();
            string path  = "testPath";
            int    value = 10;

            op.AppendAddPropertyOp(path, value);
            string operations = op.Serialize();

            // There should be a single operation added.
            var jArray = JArray.Parse(operations);

            jArray.Count.Should().Be(1);

            // The patch operation added should be an "add" operation.
            JToken jObject = jArray.First;

            jObject.Value <string>(Op).Should().Be(Add);
        }
        private async Task UpdateTargetTemperaturePropertyAsync()
        {
            const string targetTemperaturePropertyName = "targetTemperature";
            var          updateOperation = new UpdateOperationsUtility();

            // Choose a random value to assign to the targetTemperature property
            int desiredTargetTemperature = Random.Next(0, 100);

            // First let's take a look at when the property was updated and what was it set to.
            HttpOperationResponse <ThermostatTwin, DigitalTwinGetHeaders> getDigitalTwinResponse = await _digitalTwinClient
                                                                                                   .GetDigitalTwinAsync <ThermostatTwin>(_digitalTwinId);

            double?currentTargetTemperature = getDigitalTwinResponse.Body.TargetTemperature;

            if (currentTargetTemperature != null)
            {
                DateTimeOffset targetTemperatureDesiredLastUpdateTime = getDigitalTwinResponse.Body.Metadata.TargetTemperature.LastUpdateTime;
                _logger.LogDebug($"The property {targetTemperaturePropertyName} was last updated on " +
                                 $"{targetTemperatureDesiredLastUpdateTime.ToLocalTime()} `" +
                                 $" with a value of {getDigitalTwinResponse.Body.Metadata.TargetTemperature.DesiredValue}.");

                // The property path to be replaced should be prepended with a '/'
                updateOperation.AppendReplacePropertyOp($"/{targetTemperaturePropertyName}", desiredTargetTemperature);
            }
            else
            {
                _logger.LogDebug($"The property {targetTemperaturePropertyName} was never set on the ${_digitalTwinId} digital twin.");

                // The property path to be added should be prepended with a '/'
                updateOperation.AppendAddPropertyOp($"/{targetTemperaturePropertyName}", desiredTargetTemperature);
            }

            _logger.LogDebug($"Update the {targetTemperaturePropertyName} property on the " +
                             $"{_digitalTwinId} digital twin to {desiredTargetTemperature}.");
            HttpOperationHeaderResponse <DigitalTwinUpdateHeaders> updateDigitalTwinResponse = await _digitalTwinClient
                                                                                               .UpdateDigitalTwinAsync(_digitalTwinId, updateOperation.Serialize());

            _logger.LogDebug($"Update {_digitalTwinId} digital twin response: {updateDigitalTwinResponse.Response.StatusCode}.");

            // Print the Thermostat digital twin
            await GetAndPrintDigitalTwinAsync <ThermostatTwin>();
        }
        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);
            }
        }