【问题标题】:IoT Device Streaming is not connecting物联网设备流未连接
【发布时间】:2020-05-28 14:09:36
【问题描述】:

我正在探索Azure IoT Hub Device Streams 功能。

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

客户端正在使用以下算法等待传入连接(使用 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 中心的连接字符串

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

DeviceStreamRequest deviceStreamRequest = new DeviceStreamRequest("portal");

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

我无法建立连接。 CreateStreamAsync 调用在 1 分钟后超时,客户端似乎永远不会退出 WaitForDeviceStreamRequestAsync 调用。

我已关注troubleshooting guide 以了解发生了什么,但我没有得到任何信息:

问题

为什么我错过了会阻止 IoT Device Streaming 连接的内容?

【问题讨论】:

    标签: azure azure-iot-hub azure-iot-sdk


    【解决方案1】:

    请注意,Azure IoT 中心设备流功能仍处于公共预览阶段(一年多)。 您在设备端使用 SDK 1.29.0-preview-004,在服务端使用 1.27.0-preview-004 和示例 DeviceStreamingSample 来自 azure-iot-samples-csharp-master 包。

    设备流功能用于服务和设备之间的握手过程,与调用设备方法相同的通信概念。可以使用 REST POST 请求轻松测试此握手阶段。

    出于演示目的,我将使用我的IoT Hub Tester,其中已实现设备流功能,请参阅附录 A2 部分中的更多详细信息。

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

    第 2 步。使用 REST 客户端工具生成 POST 请求。以下网址供我测试:

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

    标题:

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

    有效载荷: 任何或为空

    当 POST 已发送到 device1 时,以下屏幕 sn-p 演示:

    下面的 sn-p 显示了在 WaitForDeviceStreamRequestAsync 方法之后的断点处停止程序:

    设备和服务(在本例中是我的测试器)之间的完整握手和流式传输显示在以下屏幕 sn-p 中:

    正如我所提到的,Azure IoT Hub Tester 已经实现了设备流功能,以下屏幕 sn-p 显示了一个流缓冲区:

    注意,为TransportType.Mqtt运行模拟设备不起作用,症状和你的一样,超时。看起来(基于 REST POST 响应),为主题订阅设备存在错误,例如 $iothub/streams/POST/#

    但是,当您的设备使用直接 MQTT 协议连接到 IoT 中心时,一切正常,请参阅我的测试仪的屏幕 sn-p,其中 device1 已连接到 IoT 中心:

    在屏幕上显示 Azure IoT Hub Tester 后,您可以使用它来测试服务 SDK 以进行流式传输,例如 SDK 示例中的以下行:

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

    并且测试器将显示 device1 流:

    总之,根据我上面的测试,当模拟设备配置为 TransportType.Amqp 协议时,您应该可以成功使用 SDK 进行流式传输。

    更新:

    在使用 REST 客户端工具的情况下,您可以在标头中看到来自设备握手的响应:

    此响应由以下行生成:

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

    基于响应头如

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

    可以通过 IoT Hub 在设备和服务之间建立 webSocket 流式通信。 请注意,在此之后,如果使用 REST 客户端工具,模拟设备将失败。

    【讨论】:

      【解决方案2】:

      问题在于我使用的 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);
      

      但是没有用。

      我意识到in the samples (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);
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-10
        相关资源
        最近更新 更多