物联网设备流无法连接

问题描述 投票:0回答:1

我正在探索 Azure IoT Hub设备流 的功能。

我有一个C#客户端连接到IoT Hub(位于美国中部)并处于活动状态。

IoT Hub - Device connected

客户端使用以下算法来等待传入的连接(使用 SDK 版本 1.29.0-preview-004)。

var buffer = new byte[1024];

using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(5));

DeviceStreamRequest streamRequest = await deviceClient.WaitForDeviceStreamRequestAsync(cancellationTokenSource.Token);

if (streamRequest is null)
    return;

在服务器端,我有一个Azure应用服务,它在一个特定的端点上被调用。它检索IoT Hub的连接字符串。

ServiceClient serviceClient = ServiceClient.CreateFromConnectionString(Constants.IoTHub.ConnectionString, TransportType.Amqp);

DeviceStreamRequest deviceStreamRequest = new DeviceStreamRequest("portal");

DeviceStreamResponse result = await serviceClient.CreateStreamAsync(serialNumber, deviceStreamRequest);

我无法建立连接。该 CreateStreamAsync 呼叫在1分钟后超时,而客户方似乎永远无法摆脱。WaitForDeviceStreamRequestAsync 呼叫。

我已经按照 故障排除指南 找出什么是怎么回事,但我没有得到任何。

enter image description here

问题:

为什么我缺少了会阻止IoT设备流连接的功能?

azure azure-iot-hub azure-iot-sdk
1个回答
1
投票

请注意,Azure IoT Hub Device Streams 功能仍处于公开预览版(一年多)。您正在使用的SDK 1.29.0-preview-004 在设备侧和 1.27.0-预览-004 在服务方面和样品 设备流样本 来自 azure-iot-samples-csharp-master......。 包。

设备流功能使用服务和设备之间的握手过程,与调用设备方法的通信概念相同。这个握手阶段可以通过一个REST POST请求进行简单的测试。

为了演示的目的,我将使用我的 物联网中枢测试仪在已实现设备流功能的地方,更多细节请参见附录A2部分。

步骤1. 为您的设备运行DeviceClientStreamingSample程序。你应该使用 Transport.Amqp. 注意,其他的人在我的测试中失败了。

第2步:使用REST客户端工具生成POST请求。使用REST客户端工具生成一个POST请求。以下是我测试的url。

https://xxxxxxxxxxx.azure-devices.net/twins/device1/streams/teststream?api-version=2018-08-30-preview

headers: payload: any or empty:

accept: application/json
iothub-streaming-response-timeout-in-seconds: 15
iothub-streaming-connect-timeout-in-seconds: 5
Authorization: sas-token

payload: any or empty

下面的屏幕片段演示了当POST已经被发送到设备1。

enter image description here

下面的片段显示了在断点处停止一个程序后 WaitForDeviceStreamRequestAsync(等待设备流请求)。 方法。

enter image description here

以下屏幕片段显示了设备和服务(在本例中是我的测试器)之间的完整握手和流媒体。enter image description here

正如我提到的,Azure IoT Hub Tester已经实现了设备流功能,下面的屏幕片段显示了一个流缓冲区。

enter image description here

注意,运行模拟设备为 运输类型.Mqtt 不工作,症状和你一样,超时。看起来(根据REST POST响应),订阅主题的设备有一个bug,例如 $iothubstreamsPOST#

然而,当你的设备使用直接的MQTT协议到IoT Hub时,一切都很好,请看我的测试仪的屏幕片段,其中的 设备1 是连接到IoT Hub的。enter image description here

一旦你有Azure IoT Hub Tester在屏幕上, 你可以用它来测试一个服务SDK的流,如以下行 从SDK样品。

DeviceStreamResponse result = await _serviceClient.CreateStreamAsync(_deviceId, deviceStreamRequest).ConfigureAwait(false);

而测试仪将显示一个 设备1 流。enter image description here

总之,根据我上面的测试,当模拟设备配置为以下情况时,你应该可以用SDKs成功地进行流式传输 运输类型.Amqp 协议。

更新。

在使用REST客户端工具的情况下,你可以在头文件中看到设备握手的响应。

enter image description here

这个响应是由以下一行生成的。

await _deviceClient.AcceptDeviceStreamRequestAsync(streamRequest, cancellationTokenSource.Token).ConfigureAwait(false);

基于响应头信息,如

iothub-streaming-is-accepted
iothub-streaming-url
iothub-streaming-auth-token

可以通过IoT Hub在设备和服务之间建立一个webSocket流媒体通信。需要注意的是,在这之后,在使用REST客户端工具的情况下,模拟设备将失败。


0
投票

问题就出在 DeviceClient 我使用的是来自于供应服务的信息。

ProvisioningDeviceClient provClient = ProvisioningDeviceClient.Create(Constants.IoTProvisioningService.GlobalDeviceEndpoint, Constants.IoTProvisioningService.IdScope, security, new ProvisioningTransportHandlerHttp());

var result = await provClient.RegisterAsync();

if (result.Status != ProvisioningRegistrationStatusType.Assigned)
    return;

var auth = new DeviceAuthenticationWithTpm(result.DeviceId, security);

--> DeviceClient deviceClient = DeviceClient.Create(result.AssignedHub, auth, TransportType.Amqp);

然后我使用的是... DeviceClient 实例来等待请求。

var buffer = new byte[1024];

using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(5));

--> DeviceStreamRequest streamRequest = await deviceClient.WaitForDeviceStreamRequestAsync(cancellationTokenSource.Token);

然而,它没有工作。

我意识到 在样本中 (DeviceClientStreamingSample),连接字符串中必须有设备ID,而我没有。

// String containing Hostname, Device Id & Device Key in one of the following formats:
//  "HostName=<iothub_host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>"
//  "HostName=<iothub_host_name>;CredentialType=SharedAccessSignature;DeviceId=<device_id>;SharedAccessSignature=SharedAccessSignature sr=<iot_host>/devices/<device_id>&sig=<token>&se=<expiry_time>";

// For this sample either
// - pass this value as a command-prompt argument
// - set the IOTHUB_DEVICE_CONN_STRING environment variable 
// - create a launchSettings.json (see launchSettings.json.template) containing the variable
private static string s_deviceConnectionString = Environment.GetEnvironmentVariable("IOTHUB_DEVICE_CONN_STRING");

所以我不再重复使用 DeviceClient 我从供应服务中得到了一个新的实例,并构建了一个新的实例(代码还没有准备好,这是一个原型)。

var buffer = new byte[1024];

using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(5));

var deviceClient = DeviceClient.CreateFromConnectionString(Constants.IoTHub.ConnectionString + $";DeviceId={Constants.Unit.SerialNumber}", TransportType.Amqp);

DeviceStreamRequest streamRequest = await deviceClient.WaitForDeviceStreamRequestAsync(cancellationTokenSource.Token).ConfigureAwait(false);

if (streamRequest is null)
    return;

await deviceClient.AcceptDeviceStreamRequestAsync(streamRequest, cancellationTokenSource.Token);

© www.soinside.com 2019 - 2024. All rights reserved.