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