【问题标题】:Sending Messages from Leaf Device Downstream device not being handled by IoT Edge running at Transparent Gateway从叶设备发送消息 未由在透明网关上运行的 IoT Edge 处理的下游设备
【发布时间】:2018-09-18 20:58:23
【问题描述】:

我已按照所有说明设置“下游设备”以通过在透明网关中运行的 IoT Edge 发送消息。我相信我的路由规则是正确的,但我的功能模块没有通过消息流接收任何消息。

这些是我遵循的说明: https://docs.microsoft.com/en-us/azure/iot-edge/how-to-create-transparent-gateway-linux

我正在使用 2 个 Linxu 虚拟机(ubuntu 16.04.5)。

  1. IoT Edge 透明网关 VM 配置有正确设置、配置和验证的所有证书。我已经能够使用来自
  2. 的 openssl 工具

openssl s_client -connect {my-gateway-machine-name-dns-name}.centralus.cloudapp.azure.com:8883 -CAfile /certs/certs/azure-iot-test-only.root.ca.cert .pem -showcerts

  1. 在安装并验证了证书的 Linux VM 上运行的下游设备。我的连接字符串如下:

    HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key}=GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp .azure.com

一个。我已经验证我使用 openssl 工具成功验证了 SSL 证书。 湾。我在下游设备中使用以下内容使用 NodeJS SDK 进行连接

var client = DeviceClient.fromConnectionString(connectionString, Mqtt); C。我可以看到消息显示在云中的 Azure IoT 中心,但我无法让我的模块在 IoT Edge 透明网关上运行。

  1. 这是我为 edgeHub 配置的路由规则,在示例文档页面的“路由来自下游设备的消息”中指定。

这是示例文档显示的内容: { "routes":{ "sensorToAIInsightsInput1":"FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint(\"/modules/ai_insights/inputs/input1\")", "AIInsightsToIoTHub":"FROM /messages/模块/ai_insights/outputs/output1 INTO $upstream" } }

这是我的路由配置设置为: “路线”:{ "downstreamBatterySensorToBatteryDataFunctionInput1": "FROM /* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint(\"/modules/BatteryDataFunctionModule/inputs/input1\")", “BatteryDataFunctionModuleToIoTHub”:“从 /messages/modules/BatteryDataFunctionModule/outputs/* INTO $upstream” }

** 请注意,我使用了“FROM /* WHERE NOT IS_DEFINED”和“FROM /messages/* WHERE NOT IS_DEFINED”

  1. 我在 IoT Edge 上的模块设置为函数。当我使用开箱即用的示例时,其中模拟器设备是在 IoT Edge 上运行的另一个模块,然后我的函数被正确命中。只有当我尝试使用“下游设备”时才会触发模块。

我已启用在透明网关上运行的“IoT Edge 服务的调试日志记录”。

This is the basic Run method for the Function module:

#r "Microsoft.Azure.Devices.Client"
#r "Newtonsoft.Json"

using System.IO;
using Microsoft.Azure.Devices.Client;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

// Filter messages based on the temperature value in the body of the     message and the temperature threshold value.
public static async Task Run(Message messageReceived, IAsyncCollector<Message> output, TraceWriter log)
{

如何确定如何让我的模块在 IoT Edge 中运行以被下游设备命中/触发?

【问题讨论】:

    标签: azure iot azure-iot-hub azure-iot-edge


    【解决方案1】:

    所以,您说您看到消息显示在 IoT Hub 中,但没有显示在 Edge 中...有几件事:

    您将此作为连接字符串发布到您的节点应用程序中: HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key}=GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure。 com

    您是否准确地复制/粘贴了这个?我问的原因是,在共享访问密钥和单词“GatewayHostName”之间,你有一个等号而不是分号..

    应该是: HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key};GatewayHostName={my-gateway-machine-name-dns-name}.centralus.cloudapp.azure。 com

    (请注意 GatewayHostName 之前的 ';'...如果您确实在那里有等号而不是分号,那么不知道会导致什么样的混乱 :-)

    其次,在您的路线中,您调用模块 BatteryDataFunctionModule.. 只是想确保模块名称准确无误,包括区分大小写。你可能知道,但不想假设..

    最后,如果以上两件事都检查了,您能否添加一个附加调试路由,将“传入数据”也发送到 IoTHub..
    "FROM /* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream"

    因此我们可以确保消息实际上是通过 iot edge 发送的。

    【讨论】:

    • 顺便说一句 - 我的意思是在上面的回复中添加,因为您说您看到的数据显示在 IoT Hub 中,但没有显示在 IoT Edge 中,并且根据您没有路由来判断应该将您的设备数据直接路由到 IoTHub(仅路由到您的模块),连接字符串中的等号会导致它被错误地解析..所以我的猜测是,正因为如此,GatewayHostName 参数被忽略并且默认情况下,节点客户端只是直接与 IoT Hub 对话,甚至不会尝试访问 IoT Edge。
    • @steve-busby-msft,我实际上错过了“;”分号。我已经进行了更改,但我仍然没有看到消息受到我的路由规则的影响。我还添加了您提到的其他路由,这不会拦截我的消息并将它们发送到 IoT 中心。
    • @steve-busby-msft。此外,当我使用默认路由规则在我的 IoTEdge 设备(作为所有示例随附的设备)上运行一个模块时,我的 Function 模块每次都会被命中,没有任何问题。 “tempSensor”:{“版本”:“1.0”,“类型”:“docker”,“状态”:“运行”,“restartPolicy”:“始终”,“设置”:{“图像”:“mcr.microsoft .com/azureiotedge-simulated-temperature-sensor:1.0", "createOptions": "" } },
    • "routes": { "sensorToBatteryDataFunctionModule": "FROM /messages/modules/tempSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/BatteryDataFunctionModule/inputs/input1\")", "debuggingRoute" : "FROM /* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream", "downstreamBatterySensorToBatteryDataFunctionInput1": "FROM /* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint(\"/modules/BatteryDataFunctionModule/inputs/input1\")", "BatteryDataFunctionModuleToIoTHub": "FROM /messages/modules/BatteryDataFunctionModule/outputs/* INTO $upstream" }
    • 我已完成所有更改,但无法让消息通过 IoT Edge 设备。我还可以尝试哪些其他事情?如果我从下游设备连接字符串中删除“GatewayHostName”,那么我的消息会毫无问题地到达 IoT 中心,但我相信这完全绕过了 IoTEdge。
    【解决方案2】:

    要让下游设备进行通信,需要解决 2 个问题

    1. 感谢@Steve-Busby-Msft,我需要在 SharedAccessKey 末尾和 GatewayHostName 之前添加一个分号 (;)

    您将此作为连接字符串发布在您的节点应用程序中:HostName={IoTHubName}.azure-devices.net;DeviceId=TC51_EdgeDownStreamDevice01;SharedAccessKey={My-Shared-Access-Key}=GatewayHostName={my-gateway- machine-name-dns-name}.centralus.cloudapp.azure.com

    1. NodeJS 应用程序下游设备还必须在“应用程序级别”正确加载证书。

    注意

    的代码部分

    var edge_ca_cert_path = '[Edge CA 证书的路径]';

    Node JS Downstream Application

    'use strict';
    
    var fs = require('fs');
    var Protocol = require('azure-iot-device-mqtt').Mqtt;
    // Uncomment one of these transports and then change it in fromConnectionString to test other transports
    // var Protocol = require('azure-iot-device-http').Http;
    // var Protocol = require('azure-iot-device-amqp').Amqp;
    var Client = require('azure-iot-device').Client;
    var Message = require('azure-iot-device').Message;
    
    // 1) Obtain the connection string for your downstream device and to it
    //    append this string GatewayHostName=<edge device hostname>;
    // 2) The edge device hostname is the hostname set in the config.yaml of the Edge device
    //    to which this sample will connect to.
    //
    // The resulting string should look like the following
    //  "HostName=<iothub_host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>;GatewayHostName=<edge device hostname>"
    var connectionString = '[Downstream device IoT Edge connection string]';
    
    // Path to the Edge "owner" root CA certificate
    var edge_ca_cert_path = '[Path to Edge CA certificate]';
    
    // fromConnectionString must specify a transport constructor, coming from any transport package.
    var client = Client.fromConnectionString(connectionString, Protocol);
    
    var connectCallback = function (err) {
      if (err) {
        console.error('Could not connect: ' + err.message);
      } else {
        console.log('Client connected');
        client.on('message', function (msg) {
          console.log('Id: ' + msg.messageId + ' Body: ' + msg.data);
          // When using MQTT the following line is a no-op.
          client.complete(msg, printResultFor('completed'));
          // The AMQP and HTTP transports also have the notion of completing, rejecting or abandoning the message.
          // When completing a message, the service that sent the C2D message is notified that the message has been processed.
          // When rejecting a message, the service that sent the C2D message is notified that the message won't be processed by the device. the method to use is client.reject(msg, callback).
          // When abandoning the message, IoT Hub will immediately try to resend it. The method to use is client.abandon(msg, callback).
          // MQTT is simpler: it accepts the message by default, and doesn't support rejecting or abandoning a message.
        });
    
        // Create a message and send it to the IoT Hub every second
        var sendInterval = setInterval(function () {
          var windSpeed = 10 + (Math.random() * 4); // range: [10, 14]
          var temperature = 20 + (Math.random() * 10); // range: [20, 30]
          var humidity = 60 + (Math.random() * 20); // range: [60, 80]
          var data = JSON.stringify({ deviceId: 'myFirstDownstreamDevice', windSpeed: windSpeed, temperature: temperature, humidity: humidity });
          var message = new Message(data);
          message.properties.add('temperatureAlert', (temperature > 28) ? 'true' : 'false');
          console.log('Sending message: ' + message.getData());
          client.sendEvent(message, printResultFor('send'));
        }, 2000);
    
        client.on('error', function (err) {
          console.error(err.message);
        });
    
        client.on('disconnect', function () {
          clearInterval(sendInterval);
          client.removeAllListeners();
          client.open(connectCallback);
        });
      }
    };
    
    // Provide the Azure IoT device client via setOptions with the X509
    // Edge root CA certificate that was used to setup the Edge runtime
    var options = {
      ca : fs.readFileSync(edge_ca_cert_path, 'utf-8'),
    };
    
    client.setOptions(options, function(err) {
      if (err) {
        console.log('SetOptions Error: ' + err);
      } else {
        client.open(connectCallback);
      }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      • 1970-01-01
      • 1970-01-01
      • 2020-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多