Skip to content
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

ClientProperties related updates #2114

Merged
merged 4 commits into from
Jul 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e/test/Helpers/TestDeviceCallbackHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public async Task SetClientPropertyUpdateCallbackHandlerAsync<T>(string expected
string userContext = "myContext";

await _deviceClient
.SubscribeToWritablePropertiesEventAsync(
.SubscribeToWritablePropertyUpdateRequestsAsync(
(patch, context) =>
{
_logger.Trace($"{nameof(SetClientPropertyUpdateCallbackHandlerAsync)}: DeviceClient {_testDevice.Id} callback property: WritableProperty: {patch}, {context}");
Expand Down
12 changes: 6 additions & 6 deletions e2e/test/iothub/properties/PropertiesE2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ public static async Task Properties_DeviceSetsPropertyAndGetsItBackAsync<T>(Devi

// Validate the updated properties from the device-client
ClientProperties clientProperties = await deviceClient.GetClientPropertiesAsync().ConfigureAwait(false);
bool isPropertyPresent = clientProperties.TryGetValue<T>(propName, out T propFromCollection);
bool isPropertyPresent = clientProperties.ReportedFromClient.TryGetValue<T>(propName, out T propFromCollection);
isPropertyPresent.Should().BeTrue();
propFromCollection.Should().BeEquivalentTo<T>(propValue);

Expand Down Expand Up @@ -245,7 +245,7 @@ private async Task Properties_ServiceSetsWritablePropertyAndDeviceUnsubscribes(C

// Set a callback
await deviceClient.
SubscribeToWritablePropertiesEventAsync(
SubscribeToWritablePropertyUpdateRequestsAsync(
(patch, context) =>
{
Assert.Fail("After having unsubscribed from receiving client property update notifications " +
Expand All @@ -258,7 +258,7 @@ await deviceClient.

// Unsubscribe
await deviceClient
.SubscribeToWritablePropertiesEventAsync(null, null)
.SubscribeToWritablePropertyUpdateRequestsAsync(null, null)
.ConfigureAwait(false);

await RegistryManagerUpdateWritablePropertyAsync(testDevice.Id, propName, propValue)
Expand Down Expand Up @@ -289,7 +289,7 @@ await Task

// Validate the updated properties from the device-client
ClientProperties clientProperties = await deviceClient.GetClientPropertiesAsync().ConfigureAwait(false);
bool isPropertyPresent = clientProperties.Writable.TryGetValue<T>(propName, out T propValueFromCollection);
bool isPropertyPresent = clientProperties.WritablePropertyRequests.TryGetValue<T>(propName, out T propValueFromCollection);
isPropertyPresent.Should().BeTrue();
propValueFromCollection.Should().BeEquivalentTo<T>(propValue);

Expand All @@ -301,7 +301,7 @@ await Task
string serializedActualPropertyValue = JsonConvert.SerializeObject(actualProp);
serializedActualPropertyValue.Should().Be(JsonConvert.SerializeObject(propValue));

await deviceClient.SubscribeToWritablePropertiesEventAsync(null, null).ConfigureAwait(false);
await deviceClient.SubscribeToWritablePropertyUpdateRequestsAsync(null, null).ConfigureAwait(false);
await deviceClient.CloseAsync().ConfigureAwait(false);
}

Expand All @@ -319,7 +319,7 @@ private async Task Properties_ServiceSetsWritablePropertyAndDeviceReceivesItOnNe
await registryManager.UpdateTwinAsync(testDevice.Id, twinPatch, "*").ConfigureAwait(false);

ClientProperties clientProperties = await deviceClient.GetClientPropertiesAsync().ConfigureAwait(false);
bool isPropertyPresent = clientProperties.Writable.TryGetValue(propName, out string propFromCollection);
bool isPropertyPresent = clientProperties.WritablePropertyRequests.TryGetValue(propName, out string propFromCollection);
isPropertyPresent.Should().BeTrue();
propFromCollection.Should().Be(propValue);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ static async Task TestOperationAsync(DeviceClient deviceClient, TestDevice testD
ClientProperties clientProperties = await deviceClient.GetClientPropertiesAsync().ConfigureAwait(false);
clientProperties.Should().NotBeNull();

bool isPropertyPresent = clientProperties.TryGetValue(propName, out string propFromCollection);
bool isPropertyPresent = clientProperties.ReportedFromClient.TryGetValue(propName, out string propFromCollection);
isPropertyPresent.Should().BeTrue();
propFromCollection.Should().Be(propValue);
}
Expand Down
12 changes: 6 additions & 6 deletions e2e/test/iothub/properties/PropertiesWithComponentsE2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public static async Task PropertiesWithComponents_DeviceSetsPropertyAndGetsItBac

// Validate the updated properties from the device-client
ClientProperties clientProperties = await deviceClient.GetClientPropertiesAsync().ConfigureAwait(false);
bool isPropertyPresent = clientProperties.TryGetValue<T>(ComponentName, propName, out T propFromCollection);
bool isPropertyPresent = clientProperties.ReportedFromClient.TryGetValue<T>(ComponentName, propName, out T propFromCollection);
isPropertyPresent.Should().BeTrue();
propFromCollection.Should().BeEquivalentTo<T>(propValue);

Expand Down Expand Up @@ -252,7 +252,7 @@ private async Task PropertiesWithComponents_ServiceSetsWritablePropertyAndDevice

// Set a callback
await deviceClient.
SubscribeToWritablePropertiesEventAsync(
SubscribeToWritablePropertyUpdateRequestsAsync(
(patch, context) =>
{
Assert.Fail("After having unsubscribed from receiving client property update notifications " +
Expand All @@ -265,7 +265,7 @@ await deviceClient.

// Unsubscribe
await deviceClient
.SubscribeToWritablePropertiesEventAsync(null, null)
.SubscribeToWritablePropertyUpdateRequestsAsync(null, null)
.ConfigureAwait(false);

await RegistryManagerUpdateWritablePropertyAsync(testDevice.Id, ComponentName, propName, propValue)
Expand Down Expand Up @@ -296,7 +296,7 @@ await Task

// Validate the updated properties from the device-client
ClientProperties clientProperties = await deviceClient.GetClientPropertiesAsync().ConfigureAwait(false);
bool isPropertyPresent = clientProperties.Writable.TryGetValue<T>(ComponentName, propName, out T propFromCollection);
bool isPropertyPresent = clientProperties.WritablePropertyRequests.TryGetValue<T>(ComponentName, propName, out T propFromCollection);
isPropertyPresent.Should().BeTrue();
propFromCollection.Should().BeEquivalentTo<T>(propValue);

Expand All @@ -308,7 +308,7 @@ await Task
string serializedActualPropertyValue = JsonConvert.SerializeObject(actualProp);
serializedActualPropertyValue.Should().Be(JsonConvert.SerializeObject(propValue));

await deviceClient.SubscribeToWritablePropertiesEventAsync(null, null).ConfigureAwait(false);
await deviceClient.SubscribeToWritablePropertyUpdateRequestsAsync(null, null).ConfigureAwait(false);
await deviceClient.CloseAsync().ConfigureAwait(false);
}

Expand All @@ -331,7 +331,7 @@ private async Task PropertiesWithComponents_ServiceSetsWritablePropertyAndDevice
await registryManager.UpdateTwinAsync(testDevice.Id, twinPatch, "*").ConfigureAwait(false);

ClientProperties clientProperties = await deviceClient.GetClientPropertiesAsync().ConfigureAwait(false);
bool isPropertyPresent = clientProperties.Writable.TryGetValue(ComponentName, propName, out string propFromCollection);
bool isPropertyPresent = clientProperties.WritablePropertyRequests.TryGetValue(ComponentName, propName, out string propFromCollection);
isPropertyPresent.Should().BeTrue();
propFromCollection.Should().Be(propValue);

Expand Down
31 changes: 20 additions & 11 deletions iothub/device/src/ClientProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.Azure.Devices.Client
/// The <see cref="ClientProperties"/> class is not meant to be constructed by customer code.
/// It is intended to be returned fully populated from the client method <see cref="InternalClient.GetClientPropertiesAsync(System.Threading.CancellationToken)"/>.
/// </remarks>
public class ClientProperties : ClientPropertyCollection
public class ClientProperties
{
/// <summary>
/// Initializes a new instance of <see cref="ClientProperties"/>.
Expand All @@ -19,27 +19,36 @@ public class ClientProperties : ClientPropertyCollection
/// <inheritdoc path="/remarks" cref="ClientProperties" />
public ClientProperties()
{
Writable = new ClientPropertyCollection();
WritablePropertyRequests = new ClientPropertyCollection();
ReportedFromClient = new ClientPropertyCollection();
}

/// <summary>
/// Initializes a new instance of <see cref="ClientProperties"/> with the specified collections.
/// </summary>
/// <param name="requestedPropertyCollection">A collection of writable properties returned from IoT Hub.</param>
/// <param name="readOnlyPropertyCollection">A collection of read-only properties returned from IoT Hub.</param>
internal ClientProperties(ClientPropertyCollection requestedPropertyCollection, ClientPropertyCollection readOnlyPropertyCollection)
/// <param name="writablePropertyRequestCollection">A collection of writable property requests returned from IoT Hub.</param>
/// <param name="clientReportedPropertyCollection">A collection of client reported properties returned from IoT Hub.</param>
internal ClientProperties(ClientPropertyCollection writablePropertyRequestCollection, ClientPropertyCollection clientReportedPropertyCollection)
{
SetCollection(readOnlyPropertyCollection);
Version = readOnlyPropertyCollection.Version;
Writable = requestedPropertyCollection;
WritablePropertyRequests = writablePropertyRequestCollection;
ReportedFromClient = clientReportedPropertyCollection;
}

/// <summary>
/// The collection of writable properties.
/// The collection of writable property requests received from service.
/// </summary>
/// <remarks>
/// See the <see href="https://docs.microsoft.com/en-us/azure/iot-pnp/concepts-convention#writable-properties">Writable properties</see> documentation for more information.
/// See the <see href="https://docs.microsoft.com/azure/iot-pnp/concepts-convention#writable-properties">Writable properties</see> documentation for more information.
/// </remarks>
public ClientPropertyCollection Writable { get; private set; }
public ClientPropertyCollection WritablePropertyRequests { get; private set; }

/// <summary>
/// The collection of properties reported by the client.
/// </summary>
/// <remarks>
/// Client reported properties can either be <see href="https://docs.microsoft.com/azure/iot-develop/concepts-convention#read-only-properties">Read-only properties</see>
/// or they can be <see href="https://docs.microsoft.com/azure/iot-pnp/concepts-convention#writable-properties">Writable properties</see>.
/// </remarks>
public ClientPropertyCollection ReportedFromClient { get; private set; }
}
}
6 changes: 3 additions & 3 deletions iothub/device/src/ClientTwinProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ internal ClientTwinProperties()

internal ClientProperties ToClientProperties(PayloadConvention payloadConvention)
{
ClientPropertyCollection writablePropertyCollection = ClientPropertyCollection.FromClientTwinDictionary(Desired, payloadConvention);
ClientPropertyCollection propertyCollection = ClientPropertyCollection.FromClientTwinDictionary(Reported, payloadConvention);
ClientPropertyCollection writablePropertyRequestCollection = ClientPropertyCollection.FromClientTwinDictionary(Desired, payloadConvention);
ClientPropertyCollection clientReportedPropertyCollection = ClientPropertyCollection.FromClientTwinDictionary(Reported, payloadConvention);

return new ClientProperties(writablePropertyCollection, propertyCollection);
return new ClientProperties(writablePropertyRequestCollection, clientReportedPropertyCollection);
}
}
}
2 changes: 1 addition & 1 deletion iothub/device/src/Common/UrlEncodedDictionarySerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ private Token CreateToken(TokenType tokenType, int readCount)
// '?' is not a valid character for message property names or values, but instead signifies the start of a query string
// in the case of an MQTT topic. For this reason, we'll replace the '?' from the property key before adding it into
// application properties collection.
// https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-messages-construct
// https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-messages-construct
string tokenValue = readCount == 0 ? null : value.Substring(position - readCount, readCount).Replace(QueryStringIdentifier, string.Empty);

return new Token(tokenType, tokenValue);
Expand Down
4 changes: 2 additions & 2 deletions iothub/device/src/DeviceClient.ConventionBasedOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public Task<ClientPropertiesUpdateResponse> UpdateClientPropertiesAsync(ClientPr
/// <param name="callback">The global call back to handle all writable property updates.</param>
/// <param name="userContext">Generic parameter to be interpreted by the client code.</param>
/// <param name="cancellationToken">A cancellation token to cancel the operation.</param>
public Task SubscribeToWritablePropertiesEventAsync(Func<ClientPropertyCollection, object, Task> callback, object userContext, CancellationToken cancellationToken = default)
=> InternalClient.SubscribeToWritablePropertiesEventAsync(callback, userContext, cancellationToken);
public Task SubscribeToWritablePropertyUpdateRequestsAsync(Func<ClientPropertyCollection, object, Task> callback, object userContext, CancellationToken cancellationToken = default)
=> InternalClient.SubscribeToWritablePropertyUpdateRequestsAsync(callback, userContext, cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ internal async Task<ClientPropertiesUpdateResponse> UpdateClientPropertiesAsync(
}
}

internal Task SubscribeToWritablePropertiesEventAsync(Func<ClientPropertyCollection, object, Task> callback, object userContext, CancellationToken cancellationToken)
internal Task SubscribeToWritablePropertyUpdateRequestsAsync(Func<ClientPropertyCollection, object, Task> callback, object userContext, CancellationToken cancellationToken)
{
// Subscribe to DesiredPropertyUpdateCallback internally and use the callback received internally to invoke the user supplied Property callback.
var desiredPropertyUpdateCallback = new DesiredPropertyUpdateCallback((twinCollection, userContext) =>
Expand Down
4 changes: 2 additions & 2 deletions iothub/device/src/ModuleClient.ConventionBasedOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public Task<ClientPropertiesUpdateResponse> UpdateClientPropertiesAsync(ClientPr
/// <param name="callback">The global call back to handle all writable property updates.</param>
/// <param name="userContext">Generic parameter to be interpreted by the client code.</param>
/// <param name="cancellationToken">A cancellation token to cancel the operation.</param>
public Task SubscribeToWritablePropertiesEventAsync(Func<ClientPropertyCollection, object, Task> callback, object userContext, CancellationToken cancellationToken = default)
=> InternalClient.SubscribeToWritablePropertiesEventAsync(callback, userContext, cancellationToken);
public Task SubscribeToWritablePropertyUpdateRequestsAsync(Func<ClientPropertyCollection, object, Task> callback, object userContext, CancellationToken cancellationToken = default)
=> InternalClient.SubscribeToWritablePropertyUpdateRequestsAsync(callback, userContext, cancellationToken);
}
}
15 changes: 0 additions & 15 deletions iothub/device/src/PayloadCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,5 @@ IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

/// <summary>
/// Will set the underlying <see cref="Collection"/> of the payload collection.
/// </summary>
/// <param name="payloadCollection">The collection to get the underlying dictionary from.</param>
protected void SetCollection(PayloadCollection payloadCollection)
{
if (payloadCollection == null)
{
throw new ArgumentNullException();
}

Collection = payloadCollection.Collection;
Convention = payloadCollection.Convention;
}
}
}
6 changes: 3 additions & 3 deletions iothub/device/tests/ClientPropertiesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Azure.Devices.Client.Tests
namespace Microsoft.Azure.Devices.Client.Test
{
[TestClass]
[TestCategory("Unit")]
Expand Down Expand Up @@ -57,7 +57,7 @@ public void ClientPropertyCollection_CanEnumerateClientProperties()

// assert
// These are the device reported property values.
foreach (var deviceReportedKeyValuePairs in clientProperties)
foreach (var deviceReportedKeyValuePairs in clientProperties.ReportedFromClient)
{
if (deviceReportedKeyValuePairs.Key.Equals(StringPropertyName))
{
Expand All @@ -78,7 +78,7 @@ public void ClientPropertyCollection_CanEnumerateClientProperties()
}

// These are the property values for which service has requested an update.
foreach (var updateRequestedKeyValuePairs in clientProperties.Writable)
foreach (var updateRequestedKeyValuePairs in clientProperties.WritablePropertyRequests)
{
if (updateRequestedKeyValuePairs.Key.Equals(DoublePropertyName))
{
Expand Down
2 changes: 1 addition & 1 deletion iothub/device/tests/ClientPropertyCollectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using Microsoft.Azure.Devices.Shared;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Azure.Devices.Client.Tests
namespace Microsoft.Azure.Devices.Client.Test
{
[TestClass]
[TestCategory("Unit")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Microsoft.Azure.Devices.Client.Tests
namespace Microsoft.Azure.Devices.Client.Test
{
[TestClass]
[TestCategory("Unit")]
Expand Down
2 changes: 1 addition & 1 deletion iothub/device/tests/NumericHelpersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Azure.Devices.Client.Tests
namespace Microsoft.Azure.Devices.Client.Test
{
[TestClass]
[TestCategory("Unit")]
Expand Down
2 changes: 1 addition & 1 deletion iothub/device/tests/TimeoutHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using FluentAssertions;
using System.Threading.Tasks;

namespace Microsoft.Azure.Devices.Client.Tests
namespace Microsoft.Azure.Devices.Client.Test
{
/// <summary>
/// The timeout helper is a way of keeping track of how much time remains against a specified deadline.
Expand Down
2 changes: 1 addition & 1 deletion shared/src/PayloadConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Microsoft.Azure.Devices.Shared
/// The payload convention class.
/// </summary>
/// <remarks>The payload convention is used to define a specific serializer as well as a specific content encoding.
/// For example, IoT has a <see href="https://docs.microsoft.com/en-us/azure/iot-pnp/concepts-convention">convention</see> that is designed
/// For example, IoT has a <see href="https://docs.microsoft.com/azure/iot-pnp/concepts-convention">convention</see> that is designed
/// to make it easier to get started with products that use specific conventions by default.</remarks>
public abstract class PayloadConvention
{
Expand Down