在Lambda中订阅AWS IOT主题是否可行?

8

初学者问题。找不到之前的答案。

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

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

据我所知,Lambda不能订阅主题...在Lambda函数的上下文中这其实很有道理。

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

是的,我知道IoT Shadows,但希望避免一些复杂性。


这个问题不适合在StackOverFlow上提问,请阅读如何在SOF中编写好的问题。您必须向我们展示您尝试过什么以及您的问题确切所在之处。 - Mohammed Noureldin
我更新了一个具体的问题,但是我还没有尝试过任何东西。希望在开始之前能得到一些建议。我猜这违反了规则。 - big
3个回答

9

实际上可以做到这一点,只是不太直观。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"
});

但在 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');   
});

这种方法的一个缺点是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;
};

一个模糊问题的非常好的回答。 - Mazzi

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

谢谢你的评论,但我认为那行不通。 - big
抱歉,我还在学习如何使用Stack Overflow...据我所知,唤醒Alexa的唯一方法是通过唤醒词。您无法通过某个随机的lambda函数唤醒Alexa。整个过程需要在Alexa启动的lambda函数上下文中运行,类似于:Alexa唤醒词-> lambda -> iot-publish -> iot-subscribe -> (相同) lambda -> 返回给Alexa - big
哦,你想让触发的函数从IoT主题发布、订阅和接收?我以为你是在寻找Alexa -> lambda -> 发布 -> lambda。这可能不适合IoT。你可以考虑使用DynamoDB或SQS来传递数据。你可以将lambda函数订阅到主题上,但这会比需要的更加脆弱,特别是在规模上。 - Aaron D

0
你要找的答案是从设备向Alexa发送通知。例如:“嗨<<{User}>>,水泵<<{nameofpump}>>正在运行”,根据泵的实际状态。这更像是一个通知功能,请查看Alexa语音服务上的link,它将帮助您完成相同的操作。希望这可以帮到您。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接