/// <summary> /// Update a module's twin. /// </summary> /// <param name="twinUpdate">The properties to update. Any existing properties not referenced by this patch will be unaffected by this patch.</param> /// <param name="precondition">The condition for which this operation will execute.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The new representation of the module's twin and the http response <see cref="Response{T}"/>.</returns> public virtual Response <TwinData> UpdateTwin(TwinData twinUpdate, IfMatchPrecondition precondition = IfMatchPrecondition.IfMatch, CancellationToken cancellationToken = default) { Argument.AssertNotNull(twinUpdate, nameof(twinUpdate)); string ifMatchHeaderValue = IfMatchPreconditionExtensions.GetIfMatchHeaderValue(precondition, twinUpdate.Etag); return(_modulesRestClient.UpdateTwin(twinUpdate.DeviceId, twinUpdate.ModuleId, twinUpdate, ifMatchHeaderValue, cancellationToken)); }
public async Task <ResponseWithHeaders <IReadOnlyList <TwinData>, QueryGetTwinsHeaders> > GetTwinsAsync(QuerySpecification querySpecification, string xMsContinuation = null, string xMsMaxItemCount = null, CancellationToken cancellationToken = default) { if (querySpecification == null) { throw new ArgumentNullException(nameof(querySpecification)); } using var message = CreateGetTwinsRequest(querySpecification, xMsContinuation, xMsMaxItemCount); await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); var headers = new QueryGetTwinsHeaders(message.Response); switch (message.Response.Status) { case 200: { IReadOnlyList <TwinData> value = default; using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); List <TwinData> array = new List <TwinData>(); foreach (var item in document.RootElement.EnumerateArray()) { array.Add(TwinData.DeserializeTwinData(item)); } value = array; return(ResponseWithHeaders.FromValue(value, headers, message.Response)); }
public async Task <Response <TwinData> > GetDeviceTwinAsync(string id, CancellationToken cancellationToken = default) { if (id == null) { throw new ArgumentNullException(nameof(id)); } using var message = CreateGetDeviceTwinRequest(id); await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); switch (message.Response.Status) { case 200: { TwinData value = default; using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); if (document.RootElement.ValueKind == JsonValueKind.Null) { value = null; } else { value = TwinData.DeserializeTwinData(document.RootElement); } return(Response.FromValue(value, message.Response)); }
public async Task ModulesClient_DeviceTwinLifecycle() { string testDeviceId = $"TwinLifecycleDevice{GetRandom()}"; string testModuleId = $"TwinLifecycleModule{GetRandom()}"; DeviceIdentity device = null; ModuleIdentity module = null; IotHubServiceClient client = GetClient(); try { // Create a device device = (await client.Devices.CreateOrUpdateIdentityAsync( new DeviceIdentity { DeviceId = testDeviceId }).ConfigureAwait(false)).Value; // Create a module on that device. Note that this implicitly creates the module twin module = (await client.Modules.CreateOrUpdateIdentityAsync( new ModuleIdentity { DeviceId = testDeviceId, ModuleId = testModuleId }).ConfigureAwait(false)).Value; // Get the module twin TwinData moduleTwin = (await client.Modules.GetTwinAsync(testDeviceId, testModuleId).ConfigureAwait(false)).Value; moduleTwin.ModuleId.Should().BeEquivalentTo(testModuleId, "ModuleId on the Twin should match that of the module identity."); // Update device twin string propName = "username"; string propValue = "userA"; moduleTwin.Properties.Desired.Add(new KeyValuePair <string, object>(propName, propValue)); // TODO: (azabbasi) We should leave the IfMatchPrecondition to be the default value once we know more about the fix. Response <TwinData> updateResponse = await client.Modules.UpdateTwinAsync(moduleTwin, IfMatchPrecondition.UnconditionalIfMatch).ConfigureAwait(false); updateResponse.Value.Properties.Desired.Where(p => p.Key == propName).First().Value.Should().Be(propValue, "Desired property value is incorrect."); // Delete the module // Deleting the module happens in the finally block as cleanup. } finally { await CleanupAsync(client, device).ConfigureAwait(false); } }
/// <summary> /// Update a module twin desired properties. /// </summary> /// <param name="deviceId">Unique identifier of the device the module belongs to.</param> /// <param name="moduleId">Unique identifier of the module to be updated.</param> public async Task <TwinData> UpdateModuleTwinAsync(string deviceId, string moduleId) { SampleLogger.PrintHeader("UPDATE A MODULE TWIN"); string userPropName = "user"; try { // Get the device module #region Snippet:IotHubUpdateModuleTwin Response <TwinData> getResponse = await IoTHubServiceClient.Modules.GetTwinAsync(deviceId, moduleId); TwinData moduleTwin = getResponse.Value; Console.WriteLine($"Updating module twin: DeviceId: '{moduleTwin.DeviceId}', ModuleId: '{moduleTwin.ModuleId}', ETag: '{moduleTwin.Etag}'"); Console.WriteLine($"Setting a new desired property {userPropName} to: '{Environment.UserName}'"); moduleTwin.Properties.Desired.Add(new KeyValuePair <string, object>(userPropName, Environment.UserName)); Response <TwinData> response = await IoTHubServiceClient.Modules.UpdateTwinAsync(moduleTwin); TwinData updatedTwin = response.Value; var userPropValue = (string)updatedTwin.Properties.Desired .Where(p => p.Key == userPropName) .First() .Value; SampleLogger.PrintSuccess($"Successfully updated module twin: DeviceId: '{updatedTwin.DeviceId}', ModuleId: '{updatedTwin.ModuleId}', desired property: [{userPropName}: '{userPropValue}'], ETag: '{updatedTwin.Etag}',"); #endregion Snippet:IotHubUpdateModuleTwin return(updatedTwin); } catch (Exception ex) { // Try to cleanup before exiting with fatal error. await CleanupHelper.DeleteAllDevicesInHubAsync(IoTHubServiceClient); SampleLogger.FatalError($"Failed to update a module identity due to:\n{ex}"); throw; } }
/// <summary> /// Update a device twin desired properties. /// </summary> /// <param name="deviceId">Unique identifier of the device to be updated.</param> public async Task <TwinData> UpdateDeviceTwinAsync(string deviceId) { SampleLogger.PrintHeader("UPDATE A DEVICE TWIN"); string userPropName = "user"; try { // Get the device #region Snippet:IotHubUpdateDeviceTwin Response <TwinData> getResponse = await IoTHubServiceClient.Devices.GetTwinAsync(deviceId); TwinData deviceTwin = getResponse.Value; Console.WriteLine($"Updating device twin: DeviceId: '{deviceTwin.DeviceId}', ETag: '{deviceTwin.Etag}'"); Console.WriteLine($"Setting a new desired property {userPropName} to: '{Environment.UserName}'"); deviceTwin.Properties.Desired.Add(new KeyValuePair <string, object>(userPropName, Environment.UserName)); Response <TwinData> response = await IoTHubServiceClient.Devices.UpdateTwinAsync(deviceTwin); TwinData updatedTwin = response.Value; var userPropValue = (string)updatedTwin.Properties.Desired .Where(p => p.Key == userPropName) .First() .Value; SampleLogger.PrintSuccess($"Successfully updated device twin: DeviceId: '{updatedTwin.DeviceId}', desired property: ['{userPropName}': '{userPropValue}'], ETag: '{updatedTwin.Etag}',"); #endregion Snippet:IotHubUpdateDeviceTwin return(updatedTwin); } catch (Exception ex) { SampleLogger.FatalError($"Failed to update a device identity due to:\n{ex}"); throw; } }
public async Task ModulesClient_UpdateModuleTwin_EtagDoesNotMatch() { string testDeviceId = $"TwinLifecycleDevice{GetRandom()}"; string testModuleId = $"TwinLifecycleModule{GetRandom()}"; DeviceIdentity device = null; ModuleIdentity module = null; IotHubServiceClient client = GetClient(); try { // Create a device device = (await client.Devices.CreateOrUpdateIdentityAsync( new DeviceIdentity { DeviceId = testDeviceId }).ConfigureAwait(false)).Value; // Create a module on that device. Note that this implicitly creates the module twin module = (await client.Modules.CreateOrUpdateIdentityAsync( new ModuleIdentity { DeviceId = testDeviceId, ModuleId = testModuleId }).ConfigureAwait(false)).Value; // Get the module twin TwinData moduleTwin = (await client.Modules.GetTwinAsync(testDeviceId, testModuleId).ConfigureAwait(false)).Value; moduleTwin.ModuleId.Should().BeEquivalentTo(testModuleId, "ModuleId on the Twin should match that of the module identity."); // Update device twin string propName = "username"; string propValue = "userA"; moduleTwin.Properties.Desired.Add(new KeyValuePair <string, object>(propName, propValue)); // TODO: (azabbasi) We should leave the IfMatchPrecondition to be the default value once we know more about the fix. Response <TwinData> updateResponse = await client.Modules.UpdateTwinAsync(moduleTwin, IfMatchPrecondition.UnconditionalIfMatch).ConfigureAwait(false); updateResponse.Value.Properties.Desired.Where(p => p.Key == propName).First().Value.Should().Be(propValue, "Desired property value is incorrect."); // Perform another update using the old device object to verify precondition fails. try { // Try to update the twin with the previously up-to-date twin await client.Modules.UpdateTwinAsync(moduleTwin, IfMatchPrecondition.IfMatch).ConfigureAwait(false); Assert.Fail($"Update call with outdated ETag should fail with 412 (PreconditionFailed)"); } // We will catch the exception and verify status is 412 (PreconditionfFailed) catch (RequestFailedException ex) { Assert.AreEqual(412, ex.Status, $"Expected the update to fail with http status code 412 (PreconditionFailed)"); } // Delete the module // Deleting the module happens in the finally block as cleanup. } finally { await CleanupAsync(client, device).ConfigureAwait(false); } }
public static JobResponse JobResponse(string jobId = default, string queryCondition = default, DateTimeOffset?createdTime = default, DateTimeOffset?startTime = default, DateTimeOffset?endTime = default, long?maxExecutionTimeInSeconds = default, JobResponseType?type = default, CloudToDeviceMethodRequest cloudToDeviceMethod = default, TwinData updateTwin = default, JobResponseStatus?status = default, string failureReason = default, string statusMessage = default, DeviceJobStatistics deviceJobStatistics = default) { return(new JobResponse(jobId, queryCondition, createdTime, startTime, endTime, maxExecutionTimeInSeconds, type, cloudToDeviceMethod, updateTwin, status, failureReason, statusMessage, deviceJobStatistics)); }