使用 AWS Lambda 和 Amazon DynamoDB 实现 Serverless 的 AWS IoT 后台

您的 IoT 设备是否可以扩展到数百台或数千台设备?检索多个设备的详细信息有什么挑战吗? AWS IoT 提供了一个连接这些设备的平台,并为您的物联网工作负载构建可扩展的解决方案。

开箱即用的 AWS IoT 控制台,为您提供自己的可搜索设备注册表,可以访问设备状态和有关设备 shadows 的信息。您可以使用 AWS Lambda 和 Amazon DynamoDB 来增强和定制服务,以使用可自定义的设备数据库构建 Serverless 物联网后端,可用于存储有关设备的有用信息,如果需要的话,还可以帮助跟踪哪些设备使用激活码进行激活。

您可以使用 DynamoDB 来扩展 AWS IoT 内部设备注册表,以帮助管理设备队列,以及存储有关每个设备的特定附加数据。Lambda 提供了 AWS IoT 和 DynamoDB 之间的链接,允许您添加、更新和查询新的设备数据库后端。

在本文中,您将学习如何使用 AWS IoT rules 来使用 Lamba 来触发特定的设备注册逻辑,以将数据存储到 DynamoDB 表。然后,使用第二个 Lambda 函数在数据库中搜索特定设备序列号、随机生成的激活码以用于激活设备,并在同一个表中注册设备所有者的电子邮件。完成后,您将拥有完整功能的Serverless IoT 后台,可让您专注于自己的 IoT 解决方案和逻辑,而不是管理基础设施。

AWS Serverless 物联网系统架构图

步骤1:先决条件

在创建和部署此框架之前,必须具有以下内容:

  • 一个 AWS 帐户
  • 具有创建 AWS 资源(AWS IoT 事件和规则,Lambda 函数,DynamoDB 表,IAM 策略和角色等)的IAM用户
  • JavaScript 和安装在本地的基于 JavaScript 的 AWS SDK 用于测试部署

步骤2:构建后台

在这篇文章中,我假设你对所涉及的服务有一些基本的了解。如果没有,您可以查看相关的文档:

对于这个用例,假设你有一个名为 “myThing” 的设备。这些设备可以是任何东西:智能灯泡,智能中枢(smart hub),互联网连接的机器人,音乐播放器,智能恒温器,或具有特定传感器的任何可以使用 AWS IoT 进行管理的设备。

创建 myThing 设备时,您需要在数据库中提供一些特定信息,即:

  • Client ID
  • Serial number
  • Activation code
  • Activation status
  • Device name
  • Device type
  • Owner email
  • AWS IoT endpoint

以下是一个包的(payload)示例,其中包含要发送到特定 MQTT 主题的单个 myThing 设备的详细信息,这将触发 IoT 规则。数据是 AWS IoT 可以理解的格式,很好的旧 JSON。 例如:

{
  "clientId": "ID-91B2F06B3F05",
  "serialNumber": "SN-D7F3C8947867",
  "activationCode": "AC-9BE75CD0F1543D44C9AB",
  "activated": "false",
  "device": "myThing1",
  "type": "MySmartIoTDevice",
  "email": "not@registered.yet",
  "endpoint": "<endpoint prefix>.iot.<region>.amazonaws.com"
}

然后 rule(规则) 调用您现在创建的第一个 Lambda 函数。打开 Lambda 控制台,选择创建一个 Lambda 函数,然后按照步骤。 以下是代码:

console.log('Loading function');
var AWS = require('aws-sdk');
var dynamo = new AWS.DynamoDB.DocumentClient();
var table = "iotCatalog";

exports.handler = function(event, context) {
    //console.log('Received event:', JSON.stringify(event, null, 2));
   var params = {
    TableName:table,
    Item:{
        "serialNumber": event.serialNumber,
        "clientId": event.clientId,
        "device": event.device,
        "endpoint": event.endpoint,
        "type": event.type,
        "certificateId": event.certificateId,
        "activationCode": event.activationCode,
        "activated": event.activated,
        "email": event.email
        }
    };

    console.log("Adding a new IoT device...");
    dynamo.put(params, function(err, data) {
        if (err) {
            console.error("Unable to add device. Error JSON:", JSON.stringify(err, null, 2));
            context.fail();
        } else {
            console.log("Added device:", JSON.stringify(data, null, 2));
            context.succeed();
        }
    });
}

该函数将根据事件(如前面提供的JSON数据),将一个项目添加到名为 iotCatalog 的 DynamoDB 数据库。您现在需要创建数据库,并确保 Lambda 函数具有将项目添加到 DynamoDB 表的权限,可以通过使用适当的执行角色(execution role)进行配置。

打开 DynamoDB 控制台,选择创建表并按照步骤。对于此表,请使用以下详细信息:

Serverless IoT DynamoDB 示例

序列号用于唯一标识您的设备; 例如,如果它是具有连接到其的不同客户端设备的智能中心,则使用客户端 ID 作为排序键。

后台已经准备好了!你只需要使新的资源来一起工作; 为此,您可以配置一个 IoT 规则。

在 AWS IoT 控制台上,选择创建资源并创建规则,并使用以下设置将规则指向新创建的 Lambda 函数,也称为 iotCatalog。

AWS IoT 控制台示例

创建规则后,AWS IoT 会在后台添加权限,以便每当将消息发布到名为 registration 的 MQTT 主题时触发 Lambda 功能。 您可以使用以下 Node.js 部署代码进行测试:

var AWS = require('aws-sdk');
AWS.config.region = 'ap-northeast-1';

var crypto = require('crypto');
var endpoint = "<endpoint prefix>.iot.<region>.amazonaws.com";
var iot = new AWS.Iot();
var iotdata = new AWS.IotData({endpoint: endpoint});
var topic = "registration";
var type = "MySmartIoTDevice"

//Create 50 AWS IoT Things
for(var i = 1; i < 51; i++) {
  var serialNumber = "SN-"+crypto.randomBytes(Math.ceil(12/2)).toString('hex').slice(0,15).toUpperCase();
  var clientId = "ID-"+crypto.randomBytes(Math.ceil(12/2)).toString('hex').slice(0,12).toUpperCase();
  var activationCode = "AC-"+crypto.randomBytes(Math.ceil(20/2)).toString('hex').slice(0,20).toUpperCase();
  var thing = "myThing"+i.toString();
  var thingParams = {
    thingName: thing
  };

  iot.createThing(thingParams).on('success', function(response) {
    //Thing Created!
  }).on('error', function(response) {
    console.log(response);
  }).send();

  //Publish JSON to Registration Topic

  var registrationData = '{\n \"serialNumber\": \"'+serialNumber+'\",\n \"clientId\": \"'+clientId+'\",\n \"device\": \"'+thing+'\",\n \"endpoint\": \"'+endpoint+'\",\n\"type\": \"'+type+'\",\n \"activationCode\": \"'+activationCode+'\",\n \"activated\": \"false\",\n \"email\": \"not@registered.yet\" \n}';

  var registrationParams = {
    topic: topic,
    payload: registrationData,
    qos: 0
  };

  iotdata.publish(registrationParams, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    // else Published Successfully!
  });
  setTimeout(function(){},50);
}

//Checking all devices were created

iot.listThings().on('success', function(response) {
  var things = response.data.things;
  var myThings = [];
  for(var i = 0; i < things.length; i++) {
    if (things[i].thingName.includes("myThing")){
      myThings[i]=things[i].thingName;
    }
  }

  if (myThings.length = 50){
    console.log("myThing1 to 50 created and registered!");
  }
}).on('error', function(response) {
  console.log(response);
}).send();

console.log("Registration data on the way to Lambda and DynamoDB");

以上代码用于在 AWS IoT 中创建了 50 个IoT事件,并为每个设备生成随机客户端 ID,序列号和激活码。然后,它将设备数据作为 JSON 包发布到 IoT 主题,这反过来又触发了 Lambda 函数:

AWS Serial IoT Lambda

这里是!该功能由您的 IoT 规则成功触发,并创建了您所需的所有自定义信息的 IoT 设备数据库。您可以查询数据库,以便查找您的内容以及与其相关的任何其他详细信息。

DynamoDB 示例

在 AWS IoT 控制台中,新创建的 things 也可以在 thing 注册表中使用。

AWS Thing 注册表

现在,您可以创建证书、策略,将其附加到每个 “myThing” AWS IoT Thing,然后在配置物理设备时安装每个证书。

步骤3:激活和注册逻辑

但是,你还没有完成... 如果要使用预先生成的激活码激活现场设备,以及注册激活设备的人的电子邮件详细信息怎么办?

您需要一个第二个 Lambda 函数,与第一个函数(Basic with DynamoDB)具有相同的执行角色。 以下是代码:

console.log('Loading function');

var AWS = require('aws-sdk');
var dynamo = new AWS.DynamoDB.DocumentClient();
var table = "iotCatalog";

exports.handler = function(event, context) {
    //console.log('Received event:', JSON.stringify(event, null, 2));

   var params = {
    TableName:table,
    Key:{
        "serialNumber": event.serialNumber,
        "clientId": event.clientId,
        }
    };

    console.log("Gettings IoT device details...");
    dynamo.get(params, function(err, data) {
    if (err) {
        console.error("Unable to get device details. Error JSON:", JSON.stringify(err, null, 2));
        context.fail();
    } else {
        console.log("Device data:", JSON.stringify(data, null, 2));
        console.log(data.Item.activationCode);
        if (data.Item.activationCode == event.activationCode){
            console.log("Valid Activation Code! Proceed to register owner e-mail and update activation status");
            var params = {
                TableName:table,
                Key:{
                    "serialNumber": event.serialNumber,
                    "clientId": event.clientId,
                },
                UpdateExpression: "set email = :val1, activated = :val2",
                ExpressionAttributeValues:{
                    ":val1": event.email,
                    ":val2": "true"
                },
                ReturnValues:"UPDATED\_NEW"
            };
            dynamo.update(params, function(err, data) {
                if (err) {
                    console.error("Unable to update item. Error JSON:", JSON.stringify(err, null, 2));
                    context.fail();
                } else {
                    console.log("Device now active!", JSON.stringify(data, null, 2));
                    context.succeed("Device now active! Your e-mail is now registered as device owner, thank you for activating your Smart IoT Device!");
                }
            });
        } else {
            context.fail("Activation Code Invalid");
        }
    }
});
}

该函数仅需要使用较早的数据的一小部分:

{
  "clientId": "ID-91B2F06B3F05",
  "serialNumber": "SN-D7F3C8947867",
  "activationCode": "AC-9BE75CD0F1543D44C9AB",
  "email": "verified@registered.iot"
}

Lambda 使用散列和范围键(serialNumber 和 clientId)查询数据库,并将数据库当前预生成的激活代码与设备所有者提供的代码、电子邮件地址进行比较。 如果激活代码与数据库中的激活码匹配,则相应地在 DynamoDB 中更新激活状态和电子邮件详细信息。如果没有,用户将收到一条错误消息,并指出激活码无效。

您可以使用 Amazon API Gateway 将其转换为 API。为了做到这一点,转到 Lambda 函数并添加 API 节点,如下所示:

AWS API Gateway 结点

现在,使用 Postman 这样的工具来测试对新创建的 API 节点的访问。

Postman 测试结点

如果提供了无效的激活码,则请求者会相应地获取错误消息。

Postman 无效的激活码

返回数据库,您可以确认记录已经按需要更新了。

更新 DynamoDB

步骤4:清理

完成本教程后,删除所有新创建的资源(IoT,Lambda 函数和 DynamoDB 表)。或者,您可以保留 Lambda 功能代码以备将来参考,因为除非调用函数,否则不会产生费用。

步骤5:结论

如你所风,通过利用 AWS IoT 规则引擎的强大功能,您可以利用与 AWS Lambda 的无缝集成,以创建由 Amazon DynamoDB 提供的灵活且可扩展的 IoT 后端,可用于管理日益增长的物联网 “舰队”。

您还可以配置激活 API,以利用新创建的后端。并激活设备,以及从设备所有者注册电子邮件联系人详细信息;该信息可用于与您的用户联系,了解关于新产品或新版本的IoT产品的营销活动或简报。

原文链接:https://aws.amazon.com/cn/blogs/compute/implementing-a-serverless-aws-iot-backend-with-aws-lambda-and-amazon-dynamodb/

尚未评分
您的评分将帮助我们做出更好的玩法

观光\评论区

Copyright © 2017 玩点什么. All Rights Reserved.