private async Task ReceiveSingleMessageUsingCallbackAsync(TestDeviceType type, Client.TransportType transport) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, s_devicePrefix, type).ConfigureAwait(false); using DeviceClient deviceClient = testDevice.CreateDeviceClient(transport); using var testDeviceCallbackHandler = new TestDeviceCallbackHandler(deviceClient, testDevice, Logger); using var serviceClient = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString); (Message msg, string payload, string p1Value) = ComposeC2dTestMessage(Logger); using (msg) { await testDeviceCallbackHandler.SetMessageReceiveCallbackHandlerAsync().ConfigureAwait(false); testDeviceCallbackHandler.ExpectedMessageSentByService = msg; using var cts = new CancellationTokenSource(s_tenSeconds); Logger.Trace($"Sending C2D message from service, messageId={msg.MessageId}"); await Task .WhenAll( serviceClient.SendAsync(testDevice.Id, msg), testDeviceCallbackHandler.WaitForReceiveMessageCallbackAsync(cts.Token)) .ConfigureAwait(false); } await deviceClient.CloseAsync().ConfigureAwait(false); await serviceClient.CloseAsync().ConfigureAwait(false); }
private async Task DoNotReceiveMessagesSentBeforeSubscriptionAsync(TestDeviceType type, ITransportSettings[] settings) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, s_devicePrefix, type).ConfigureAwait(false); DeviceClient deviceClient = testDevice.CreateDeviceClient(settings); var testDeviceCallbackHandler = new TestDeviceCallbackHandler(deviceClient, testDevice, Logger); using var serviceClient = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString); (Message msg, string payload, string p1Value) = ComposeC2dTestMessage(Logger); // Subscribe to receive C2D messages over the callback. await testDeviceCallbackHandler.SetMessageReceiveCallbackHandlerAsync().ConfigureAwait(false); // Now dispose and reinitialize the client instance. deviceClient.Dispose(); deviceClient = null; testDeviceCallbackHandler.Dispose(); testDeviceCallbackHandler = null; deviceClient = testDevice.CreateDeviceClient(settings); testDeviceCallbackHandler = new TestDeviceCallbackHandler(deviceClient, testDevice, Logger); // Open the device client - for MQTT, this will connect the device with CleanSession flag set to true. // This will ensure that messages sent before the device had subscribed to c2d topic are not delivered. await deviceClient.OpenAsync().ConfigureAwait(false); // Send the message from service. Logger.Trace($"Sending C2D message from service, messageId={msg.MessageId}"); await serviceClient.SendAsync(testDevice.Id, msg).ConfigureAwait(false); // Subscribe to receive C2D messages over the callback. testDeviceCallbackHandler.ExpectedMessageSentByService = msg; await testDeviceCallbackHandler.SetMessageReceiveCallbackHandlerAsync().ConfigureAwait(false); // Wait to ensure that the message was not received. using var cts = new CancellationTokenSource(s_tenSeconds); Func <Task> receiveMessageOverCallback = async() => { await testDeviceCallbackHandler.WaitForReceiveMessageCallbackAsync(cts.Token).ConfigureAwait(false); }; receiveMessageOverCallback.Should().Throw <OperationCanceledException>(); await serviceClient.CloseAsync().ConfigureAwait(false); deviceClient.Dispose(); testDeviceCallbackHandler.Dispose(); }
private async Task ReceiveMessagesSentBeforeSubscriptionAsync(TestDeviceType type, Client.TransportType transport) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, s_devicePrefix, type).ConfigureAwait(false); DeviceClient deviceClient = testDevice.CreateDeviceClient(transport); var testDeviceCallbackHandler = new TestDeviceCallbackHandler(deviceClient, testDevice, Logger); using var serviceClient = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString); (Message msg, string payload, string p1Value) = ComposeC2dTestMessage(Logger); // Subscribe to receive C2D messages over the callback. await testDeviceCallbackHandler.SetMessageReceiveCallbackHandlerAsync().ConfigureAwait(false); // Now dispose and reinitialize the client instance. deviceClient.Dispose(); deviceClient = null; testDeviceCallbackHandler.Dispose(); testDeviceCallbackHandler = null; deviceClient = testDevice.CreateDeviceClient(transport); testDeviceCallbackHandler = new TestDeviceCallbackHandler(deviceClient, testDevice, Logger); // Open the device client - for MQTT, this will connect the device with CleanSession flag set to false. await deviceClient.OpenAsync().ConfigureAwait(false); // Send the message from service. Logger.Trace($"Sending C2D message from service, messageId={msg.MessageId}"); await serviceClient.SendAsync(testDevice.Id, msg).ConfigureAwait(false); // Subscribe to receive C2D messages over the callback. testDeviceCallbackHandler.ExpectedMessageSentByService = msg; await testDeviceCallbackHandler.SetMessageReceiveCallbackHandlerAsync().ConfigureAwait(false); // Wait to ensure that the message was received. using var cts = new CancellationTokenSource(s_tenSeconds); await testDeviceCallbackHandler.WaitForReceiveMessageCallbackAsync(cts.Token).ConfigureAwait(false); await serviceClient.CloseAsync().ConfigureAwait(false); deviceClient.Dispose(); testDeviceCallbackHandler.Dispose(); }
private async Task ReceiveMessageUsingCallbackAndUnsubscribeAsync(TestDeviceType type, Client.TransportType transport) { TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, s_devicePrefix, type).ConfigureAwait(false); using DeviceClient deviceClient = testDevice.CreateDeviceClient(transport); using var testDeviceCallbackHandler = new TestDeviceCallbackHandler(deviceClient, testDevice, Logger); using var serviceClient = ServiceClient.CreateFromConnectionString(Configuration.IoTHub.ConnectionString); // For Mqtt - we will need to subscribe to the Mqtt receive telemetry topic // before the device can begin receiving c2d messages. if (transport == Client.TransportType.Mqtt_Tcp_Only || transport == Client.TransportType.Mqtt_WebSocket_Only) { Client.Message leftoverMessage = await deviceClient.ReceiveAsync(s_fiveSeconds).ConfigureAwait(false); Logger.Trace($"Leftover message on Mqtt was: {leftoverMessage} with Id={leftoverMessage?.MessageId}"); } // First receive message using the polling ReceiveAsync() API. (Message firstMessage, _, _) = ComposeC2dTestMessage(Logger); await serviceClient.SendAsync(testDevice.Id, firstMessage).ConfigureAwait(false); Logger.Trace($"Sent C2D message from service, messageId={firstMessage.MessageId} - to be received on polling ReceiveAsync"); using Client.Message receivedFirstMessage = await deviceClient.ReceiveAsync(s_tenSeconds).ConfigureAwait(false); receivedFirstMessage.MessageId.Should().Be(firstMessage.MessageId); await deviceClient.CompleteAsync(receivedFirstMessage).ConfigureAwait(false); // Now, set a callback on the device client to receive C2D messages. await testDeviceCallbackHandler.SetMessageReceiveCallbackHandlerAsync().ConfigureAwait(false); // Now, send a message to the device from the service. (Message secondMessage, _, _) = ComposeC2dTestMessage(Logger); testDeviceCallbackHandler.ExpectedMessageSentByService = secondMessage; await serviceClient.SendAsync(testDevice.Id, secondMessage).ConfigureAwait(false); Logger.Trace($"Sent C2D message from service, messageId={secondMessage.MessageId} - to be received on callback"); // The message should be received on the callback, while a call to ReceiveAsync() should return null. using var cts = new CancellationTokenSource(s_tenSeconds); using Client.Message receivedSecondMessage = await deviceClient.ReceiveAsync(s_tenSeconds).ConfigureAwait(false); await testDeviceCallbackHandler.WaitForReceiveMessageCallbackAsync(cts.Token).ConfigureAwait(false); receivedSecondMessage.Should().BeNull(); // Now unsubscribe from receiving c2d messages over the callback. await deviceClient.SetReceiveMessageHandlerAsync(null, deviceClient).ConfigureAwait(false); // For Mqtt - since we have explicitly unsubscribed, we will need to resubscribe again // before the device can begin receiving c2d messages. if (transport == Client.TransportType.Mqtt_Tcp_Only || transport == Client.TransportType.Mqtt_WebSocket_Only) { Client.Message leftoverMessage = await deviceClient.ReceiveAsync(s_fiveSeconds).ConfigureAwait(false); Logger.Trace($"Leftover message on Mqtt was: {leftoverMessage} with Id={leftoverMessage?.MessageId}"); } // Send a message to the device from the service. (Message thirdMessage, _, _) = ComposeC2dTestMessage(Logger); await serviceClient.SendAsync(testDevice.Id, thirdMessage).ConfigureAwait(false); Logger.Trace($"Sent C2D message from service, messageId={thirdMessage.MessageId} - to be received on polling ReceiveAsync"); // This time, the message should not be received on the callback, rather it should be received on a call to ReceiveAsync(). Func <Task> receiveMessageOverCallback = async() => { await testDeviceCallbackHandler.WaitForReceiveMessageCallbackAsync(cts.Token).ConfigureAwait(false); }; using Client.Message receivedThirdMessage = await deviceClient.ReceiveAsync(s_tenSeconds).ConfigureAwait(false); receivedThirdMessage.MessageId.Should().Be(thirdMessage.MessageId); receiveMessageOverCallback.Should().Throw <OperationCanceledException>(); await deviceClient.CompleteAsync(receivedThirdMessage).ConfigureAwait(false); firstMessage.Dispose(); secondMessage.Dispose(); thirdMessage.Dispose(); await deviceClient.CloseAsync().ConfigureAwait(false); await serviceClient.CloseAsync().ConfigureAwait(false); }