可以在 lambda 中订阅 aws IOT 主题吗?

big*_*big 4 lambda subscribe amazon-web-services iot

新手问题。找不到以前的答案。

我想用 Alexa 构建一个简单的泵控制器。希望 Alexa 报告泵状态。

最简单的方法是 Alexa -> lambda -> publish_to_Iot。然后,或者可能就在发布之前,订阅另一个主题,本地控制器将向该主题发布将通过 Alexa 传回的泵状态。

就我所知,不可能从 Lambda 订阅主题……这在 lambda 函数的上下文中实际上是有意义的。

具体问题是,lambda 函数可以订阅 IoT 主题吗?

是的,我知道物联网阴影,希望避免一些复杂性。

Mic*_*nor 6

实际上可以做到这一点,只是不是非常直观。AWS-SDK 没有订阅方法,因此您需要使用 aws-iot-device-sdk。该库通常需要证书和许多其他配置信息。

var device = awsIot.jobs({
  keyPath: "./42fc9544f6-private.pem.key",
  certPath: "./42fc9544f6-certificate.pem.crt",
  caPath: "./AmazonRootCA1.pem",
  clientId: "clientPolicy", // name of the policy
  host: "your-endpoint.iot.us-east-1.amazonaws.com"
});
Run Code Online (Sandbox Code Playgroud)

但在 lambda 中使用客户端证书没有意义。lambda 已经在 IAM 用户下运行,所以您应该能够利用它吧?事实证明你可以,但需要一点挖掘。aws-iot-device-sdk.js 库将从 Lambda 中的环境变量(process.env.AWS_ACCESS_KEY_ID、process.env.AWS_SECRET_ACCESS_KEY)中读取凭证。但是你必须使用 wss 协议。

var awsIot = require('aws-iot-device-sdk');

device = awsIot.jobs({
  host: 'a1jcq6m7bg94jb-ats.iot.us-east-1.amazonaws.com',
  protocol: 'wss'});

device
  .on('connect', function() {
    console.log('connected. subscribing to topic...');
    device.subscribe(topic);
    console.log('subscribed to topic');   
});
Run Code Online (Sandbox Code Playgroud)

这种方法的缺陷之一是 Lambda 中存在自然延迟,当然还有额外的延迟来建立与主题的连接。这确实会减慢速度。一个很好的模式是让 lambda 侦听特定于该 Lambda 实例的主题(例如 lambda/some-uuid/response),然后当您向设备发布消息时,您可以要求它对该主题做出响应. 好处是只要 Lambda 函数启动并运行,主题就会存在。如果交通拥堵或保持温暖,那可能需要几个小时。使用此模型,建立连接和订阅主题没有延迟。在我的测试中,这非常快且延迟低。

这就是我处理订阅的方式。

var subscriber = null;

const lambdaUUID = uuidv4();
const topic = 'lambda/' + lambdaUUID + '/response';

device.on('message', function(topic, payload) {
  console.log('incoming message on topic' + topic);
  if ( subscriber ) {
    console.log('calling subscriber');
    subscriber(topic, payload);
  } else {
    console.log("no subscriber");
  }
});


exports.handler =  async function(event, context) {
  console.log("EVENT: \n" + JSON.stringify(event, null, 2));

  var deviceRequest = {"some":"stuff", callback: topic};

  const promise = new Promise(function(resolve, reject) {
    subscriber = function(topic, payload ) {
      console.log('subscriber called, resolving promise...');
      resolve("SUCCESS " + payload);
    };
  });  

  device.publish('things/THING1234/incoming', JSON.stringify(deviceRequest,null,''), { qos:0 }, function(err, data) {
    console.log("publishing message to device",err,data);
  });

  return promise;
};
Run Code Online (Sandbox Code Playgroud)


小智 1

您可以触发 Lambda 函数以响应使用规则的匹配过滤器(过滤器将与主题匹配)。