-
Notifications
You must be signed in to change notification settings - Fork 5.1k
(feat): Implement Modules client #12673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
9b79574
Implement Modules client
azabbasi 54ce8ed
Update API Design.md
azabbasi 03a0a15
Fix all warnings and make sure solution builds
azabbasi fe3fffb
Format files
azabbasi d59e7d7
remove unnecessary code
azabbasi 7cce057
cr comments
azabbasi ad24b72
reference http response type
azabbasi 2108d2a
update async pagable comments
azabbasi 743404b
update module client summary
azabbasi 10a089f
add link to the summary
azabbasi 6b19d7c
Update Readme to pass code analysys
azabbasi c6a9f1a
Update README.md
azabbasi 86312b1
Export APIs
azabbasi 8fa846b
make query string constant
azabbasi b904adc
Update API design md file to reference implementation.
azabbasi 7d9f736
xml comments for protector constructor
azabbasi c38b517
Update xml comments.
azabbasi 628e9ff
fix typo
azabbasi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next
Next commit
Implement Modules client
- Loading branch information
commit 9b795748993b2124769ac90410658f0295dbfd13
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,25 +1,313 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Text; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using Azure.Core; | ||
| using Azure.Iot.Hub.Service.Models; | ||
|
|
||
| namespace Azure.Iot.Hub.Service | ||
| { | ||
| /// <summary> | ||
| /// Modules Client place holder | ||
| /// Modules Client. | ||
| /// </summary> | ||
| public class ModulesClient | ||
| { | ||
| private const string ContinuationTokenHeader = "x-ms-continuation"; | ||
|
|
||
| private readonly RegistryManagerRestClient _registryManagerClient; | ||
| private readonly TwinRestClient _twinClient; | ||
| private readonly DeviceMethodRestClient _deviceMethodClient; | ||
|
|
||
| protected ModulesClient() | ||
| { | ||
| } | ||
|
|
||
| internal ModulesClient(RegistryManagerRestClient registryManagerClient, TwinRestClient twinRestClient, DeviceMethodRestClient deviceMethodRestClient) | ||
| { | ||
| Argument.AssertNotNull(registryManagerClient, nameof(registryManagerClient)); | ||
| Argument.AssertNotNull(twinRestClient, nameof(twinRestClient)); | ||
| Argument.AssertNotNull(deviceMethodRestClient, nameof(deviceMethodRestClient)); | ||
|
|
||
| _registryManagerClient = registryManagerClient; | ||
| _twinClient = twinRestClient; | ||
| _deviceMethodClient = deviceMethodRestClient; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Create a module identity. | ||
| /// </summary> | ||
| /// <param name="moduleIdentity">The module identity to create.</param> | ||
| /// <param name="precondition">The condition on which to perform this operation. To create a device identity, this value must be equal to <see cref="IfMatchPrecondition.Unconditional"/>.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The created module identity.</returns> | ||
| public virtual Task<Response<ModuleIdentity>> CreateOrUpdateIdentityAsync( | ||
| ModuleIdentity moduleIdentity, | ||
| IfMatchPrecondition precondition = IfMatchPrecondition.IfMatch, | ||
| CancellationToken cancellationToken = default) | ||
| { | ||
| Argument.AssertNotNull(moduleIdentity, nameof(moduleIdentity)); | ||
| string ifMatchHeaderValue = IfMatchPreconditionExtensions.GetIfMatchHeaderValue(precondition, moduleIdentity.Etag); | ||
| return _registryManagerClient.CreateOrUpdateModuleAsync(moduleIdentity.DeviceId, moduleIdentity.ModuleId, moduleIdentity, ifMatchHeaderValue, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Create a module identity. | ||
| /// </summary> | ||
| /// <param name="moduleIdentity">The module identity to create.</param> | ||
| /// <param name="precondition">The condition on which to perform this operation. To create a module identity, this value must be equal to <see cref="IfMatchPrecondition.Unconditional"/>.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The created module identity.</returns> | ||
| public virtual Response<ModuleIdentity> CreateOrUpdateIdentity( | ||
| ModuleIdentity moduleIdentity, | ||
| IfMatchPrecondition precondition = IfMatchPrecondition.IfMatch, | ||
| CancellationToken cancellationToken = default) | ||
| { | ||
| Argument.AssertNotNull(moduleIdentity, nameof(moduleIdentity)); | ||
| string ifMatchHeaderValue = IfMatchPreconditionExtensions.GetIfMatchHeaderValue(precondition, moduleIdentity.Etag); | ||
| return _registryManagerClient.CreateOrUpdateModule(moduleIdentity.DeviceId, moduleIdentity.ModuleId, moduleIdentity, ifMatchHeaderValue, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Get a single module identity. | ||
| /// </summary> | ||
| /// <param name="deviceId">The unique identifier of the device identity.</param> | ||
| /// <param name="moduleId">The unique identifier of the module to get.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The retrieved module identity.</returns> | ||
| public virtual Task<Response<ModuleIdentity>> GetIdentityAsync(string deviceId, string moduleId, CancellationToken cancellationToken = default) | ||
| { | ||
| return _registryManagerClient.GetModuleAsync(deviceId, moduleId, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// place holder | ||
| /// Get a single module identity. | ||
| /// </summary> | ||
| #pragma warning disable AZC0007 // DO provide a minimal constructor that takes only the parameters required to connect to the service. | ||
| public ModulesClient() | ||
| #pragma warning restore AZC0007 // DO provide a minimal constructor that takes only the parameters required to connect to the service. | ||
| /// <param name="deviceId">The unique identifier of the device identity.</param> | ||
| /// <param name="moduleId">The unique identifier of the module to get.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The retrieved module identity.</returns> | ||
| public virtual Response<ModuleIdentity> GetIdentity(string deviceId, string moduleId, CancellationToken cancellationToken = default) | ||
| { | ||
| return _registryManagerClient.GetModule(deviceId, moduleId, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Get a set of module identities for a specific device. | ||
| /// </summary> | ||
| /// <param name="deviceId">The unique identifier of the device.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>A list of modules identities within a device.</returns> | ||
| public virtual Task<Response<IReadOnlyList<ModuleIdentity>>> GetIdentitiesAsync(string deviceId, CancellationToken cancellationToken = default) | ||
| { | ||
| Argument.AssertNotNullOrEmpty(deviceId, nameof(deviceId)); | ||
| return _registryManagerClient.GetModulesOnDeviceAsync(deviceId, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Get a set of module identities for a specific device. | ||
| /// </summary> | ||
| /// <param name="deviceId">The unique identifier of the device.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>A list of modules identities within a device.</returns> | ||
| public virtual Response<IReadOnlyList<ModuleIdentity>> GetIdentities(string deviceId, CancellationToken cancellationToken = default) | ||
| { | ||
| Argument.AssertNotNullOrEmpty(deviceId, nameof(deviceId)); | ||
| return _registryManagerClient.GetModulesOnDevice(deviceId, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Delete a single module identity. | ||
| /// </summary> | ||
| /// <param name="moduleIdentity">The module identity to delete. If no ETag is present on the module identity, then the condition must be equal to <see cref="IfMatchPrecondition.Unconditional"/> or equal to <see cref="IfMatchPrecondition.UnconditionalIfMatch"/>.</param> | ||
| /// <param name="precondition">The condition on which to delete the module identity.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The http response.</returns> | ||
| public virtual Task<Response> DeleteIdentityAsync( | ||
| ModuleIdentity moduleIdentity, | ||
| IfMatchPrecondition precondition = IfMatchPrecondition.IfMatch, | ||
| CancellationToken cancellationToken = default) | ||
| { | ||
| Argument.AssertNotNull(moduleIdentity, nameof(moduleIdentity)); | ||
| string ifMatchHeaderValue = IfMatchPreconditionExtensions.GetIfMatchHeaderValue(precondition, moduleIdentity.Etag); | ||
| return _registryManagerClient.DeleteModuleAsync(moduleIdentity.DeviceId, moduleIdentity.ModuleId, ifMatchHeaderValue, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Delete a single module identity. | ||
| /// </summary> | ||
| /// <param name="moduleIdentity">The module identity to delete. If no ETag is present on the module identity, then the condition must be equal to <see cref="IfMatchPrecondition.Unconditional"/> or equal to <see cref="IfMatchPrecondition.UnconditionalIfMatch"/>.</param> | ||
| /// <param name="precondition">The condition on which to delete the module identity.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The http response.</returns> | ||
| public virtual Response DeleteIdentity( | ||
| ModuleIdentity moduleIdentity, | ||
| IfMatchPrecondition precondition = IfMatchPrecondition.IfMatch, | ||
| CancellationToken cancellationToken = default) | ||
| { | ||
| Argument.AssertNotNull(moduleIdentity, nameof(moduleIdentity)); | ||
| string ifMatchHeaderValue = IfMatchPreconditionExtensions.GetIfMatchHeaderValue(precondition, moduleIdentity.Etag); | ||
| return _registryManagerClient.DeleteModule(moduleIdentity.DeviceId, moduleIdentity.ModuleId, ifMatchHeaderValue, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// List a set of module twins. | ||
| /// </summary> | ||
| /// <param name="pageSize">The size of each page to be retrieved from the service. Service may override this size.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>A pageable set of module twins.</returns> | ||
| public virtual AsyncPageable<TwinData> GetTwinsAsync(int? pageSize = null, CancellationToken cancellationToken = default) | ||
| { | ||
| async Task<Page<TwinData>> FirstPageFunc(int? pageSizeHint) | ||
| { | ||
| var querySpecification = new QuerySpecification | ||
| { | ||
| Query = "select * from modules" | ||
azabbasi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }; | ||
|
|
||
| Response<IReadOnlyList<TwinData>> response = | ||
| await _registryManagerClient.QueryIotHubAsync(querySpecification, null, pageSizeHint?.ToString(), cancellationToken).ConfigureAwait(false); | ||
|
|
||
| response.GetRawResponse().Headers.TryGetValue(ContinuationTokenHeader, out string continuationToken); | ||
|
|
||
| return Page.FromValues(response.Value, continuationToken, response.GetRawResponse()); | ||
| } | ||
|
|
||
| async Task<Page<TwinData>> NextPageFunc(string nextLink, int? pageSizeHint) | ||
| { | ||
| var querySpecification = new QuerySpecification(); | ||
|
|
||
| Response<IReadOnlyList<TwinData>> response = | ||
| await _registryManagerClient.QueryIotHubAsync(querySpecification, nextLink, pageSizeHint?.ToString(), cancellationToken).ConfigureAwait(false); | ||
|
|
||
| response.GetRawResponse().Headers.TryGetValue(ContinuationTokenHeader, out string continuationToken); | ||
| return Page.FromValues(response.Value, continuationToken, response.GetRawResponse()); | ||
| } | ||
|
|
||
| return PageableHelpers.CreateAsyncEnumerable(FirstPageFunc, NextPageFunc, pageSize); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// List a set of module twins. | ||
| /// </summary> | ||
| /// <param name="pageSize">The size of each page to be retrieved from the service. Service may override this size.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>A pageable set of module twins.</returns> | ||
| public virtual Pageable<TwinData> GetTwins(int? pageSize = null, CancellationToken cancellationToken = default) | ||
| { | ||
| Page<TwinData> FirstPageFunc(int? pageSizeHint) | ||
| { | ||
| var querySpecification = new QuerySpecification | ||
| { | ||
| Query = "select * from modules" | ||
| }; | ||
|
|
||
| Response<IReadOnlyList<TwinData>> response = _registryManagerClient.QueryIotHub(querySpecification, null, pageSizeHint?.ToString(), cancellationToken); | ||
|
|
||
| response.GetRawResponse().Headers.TryGetValue(ContinuationTokenHeader, out string continuationToken); | ||
|
|
||
| return Page.FromValues(response.Value, continuationToken, response.GetRawResponse()); | ||
| } | ||
|
|
||
| Page<TwinData> NextPageFunc(string nextLink, int? pageSizeHint) | ||
| { | ||
| var querySpecification = new QuerySpecification(); | ||
| Response<IReadOnlyList<TwinData>> response = _registryManagerClient.QueryIotHub(querySpecification, nextLink, pageSizeHint?.ToString(), cancellationToken); | ||
| response.GetRawResponse().Headers.TryGetValue(ContinuationTokenHeader, out string continuationToken); | ||
| return Page.FromValues(response.Value, continuationToken, response.GetRawResponse()); | ||
| } | ||
|
|
||
| return PageableHelpers.CreateEnumerable(FirstPageFunc, NextPageFunc, pageSize); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Get a module's twin. | ||
| /// </summary> | ||
| /// <param name="deviceId">The unique identifier of the device identity.</param> | ||
| /// <param name="moduleId">The unique identifier of the module identity.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The module's twin, including reported properties and desired properties.</returns> | ||
| public virtual Task<Response<TwinData>> GetTwinAsync(string deviceId, string moduleId, CancellationToken cancellationToken = default) | ||
| { | ||
| return _twinClient.GetModuleTwinAsync(deviceId, moduleId, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Get a module's twin. | ||
| /// </summary> | ||
| /// <param name="deviceId">The unique identifier of the device identity.</param> | ||
| /// <param name="moduleId">The unique identifier of the module identity.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The module's twin, including reported properties and desired properties.</returns> | ||
| public virtual Response<TwinData> GetTwin(string deviceId, string moduleId, CancellationToken cancellationToken = default) | ||
| { | ||
| return _twinClient.GetModuleTwin(deviceId, moduleId, cancellationToken); | ||
| } | ||
|
|
||
| /// <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.</returns> | ||
| public virtual Task<Response<TwinData>> UpdateTwinAsync( | ||
| TwinData twinUpdate, | ||
| IfMatchPrecondition precondition = IfMatchPrecondition.IfMatch, | ||
| CancellationToken cancellationToken = default) | ||
| { | ||
| Argument.AssertNotNull(twinUpdate, nameof(twinUpdate)); | ||
| string ifMatchHeaderValue = IfMatchPreconditionExtensions.GetIfMatchHeaderValue(precondition, twinUpdate.Etag); | ||
| return _twinClient.UpdateModuleTwinAsync(twinUpdate.DeviceId, twinUpdate.ModuleId, twinUpdate, ifMatchHeaderValue, cancellationToken); | ||
| } | ||
|
|
||
| /// <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.</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 _twinClient.UpdateModuleTwin(twinUpdate.DeviceId, twinUpdate.ModuleId, twinUpdate, ifMatchHeaderValue, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Invoke a method on a module. | ||
| /// </summary> | ||
| /// <param name="deviceId">The unique identifier of the device.</param> | ||
| /// <param name="moduleId">The unique identifier of the module identity to invoke the method on.</param> | ||
| /// <param name="directMethodRequest">The details of the method to invoke.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The result of the method invocation.</returns> | ||
| public virtual Task<Response<CloudToDeviceMethodResponse>> InvokeMethodAsync( | ||
| string deviceId, | ||
| string moduleId, | ||
| CloudToDeviceMethodRequest directMethodRequest, | ||
| CancellationToken cancellationToken = default) | ||
| { | ||
| return _deviceMethodClient.InvokeModuleMethodAsync(deviceId, moduleId, directMethodRequest, cancellationToken); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Invoke a method on a module. | ||
| /// </summary> | ||
| /// <param name="deviceId">The unique identifier of the device.</param> | ||
| /// <param name="moduleId">The unique identifier of the module identity to invoke the method on.</param> | ||
| /// <param name="directMethodRequest">The details of the method to invoke.</param> | ||
| /// <param name="cancellationToken">The cancellation token.</param> | ||
| /// <returns>The result of the method invocation.</returns> | ||
| public virtual Response<CloudToDeviceMethodResponse> InvokeMethod( | ||
| string deviceId, | ||
| string moduleId, | ||
| CloudToDeviceMethodRequest directMethodRequest, | ||
| CancellationToken cancellationToken = default) | ||
| { | ||
| return _deviceMethodClient.InvokeModuleMethod(deviceId, moduleId, directMethodRequest, cancellationToken); | ||
| } | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.