亚马逊AWS官方博客

Amazon IoT 设备批量注册和数据路由的自动化部署和实现方案

无论在工业物联网,还是在智能家居等各个行业,随着越来越多的物联网设备的接入,需要我们将这些设备批量的自动注册到物联网云平台中。这些设备往往在出厂时都不知道具体会连接到哪个云平台中,在现有的通用物联网云平台中往往都采用双向证书安全认证的方式,需要事先将Bootstrap 证书或者设备证书下载到设备然后才能注册或者安全连接到云平台。另外,IoT 设备连接后,随着对 IoT 数据的越来越多的获取,对这些 IoT 数据需要进行分层次存储和处理,比如说将所有 IoT 数据存放在 S3 数据湖中,将重要的数据存放在关系型数据库中,以及将需要实时展现的数据存放在 Redis 内存数据库中等等。同时,对云平台物联网业务和规则的自动化部署也能很好的帮助客户对物联网平台业务进行快速的部署和搭建。

在这篇博文中,我们将向您介绍如何帮助客户解决这些方面的挑战,在 Amazong IoT 上实现将设备的批量自动注册以及数据路由的自动化部署方案。

  • IoT 设备的批量注册在云端的自动化部署,以及实现设备在物联网云端的自动注册和与云端的安全连接
  • IoT 规则定义的自动化部署
  • IoT 数据存储至 S3、提供通过 Lambda 存储至 RDS (SQL Server) 和ElastiCache (Redis) 数据库,供应用系统作进一步处理

方案概述

从总体方案架构和流程来说,首先需要支持大量设备的自动注册,在IoT云端部署设备自动注册服务,同时在物联网设备支持将安全连接至 Amazon IoT Core 云端所需要的 IoT Endpoint,Bootstrap 启动设备证书和私钥进行申请和下载保存到本地,根据这些 Bootstrap 证书和私钥来获取正式可用的设备证书和私钥。然后,从物联网设备端将采集到的数据进行相关处理,然后再上传到 Amazon IoT Core 云端。在 IoT 云端,则将这些数据进行处理和保存到 S3,RDS (SQL Server)数据库和ElastiCache (Redis) 数据库中,供进一步的数据处理和呈现。最后,所有云端的服务都实现了自动化部署,提供 CloudFormation 模版,使得能在类似系统中得到快速复制和部署。

具体的总体方案架构如下图所示,绿色背景部分是设备端,蓝色背景部分是云端。

流程如下:

  1. 设备端设备向 Web 服务获取 IoT Endpoint URL,Bootstrap 证书和私钥等信息
  2. 设备端设备根据上述信息将设备自动注册到 Amazon IoT 云端
  3. 设备端设备从本地获取传感器数据,生成相关JSON数据,并将这些数据发送(MQTT Publish)至Amazon IoT云端
  4. Amazon IoT 接收到这些数据,规则引擎根据设定IoT规则操作将数据路由至S3或Lambda中,Lambda将数据存储至云端RDS (SQL Server)数据库或ElastiCache (Redis)数据库中

物联网云端方案

在物联网云端,主要需要提供两方面的功能。第一,提供设备自动注册服务使得能支持设备上电后能自动注册到Amazon云端,使得设备端设备与Amazon云能安全连接和通信。第二,通过规则引擎,根据MQTT主题及其JSON内容,使得从设备端设备发送过来的数据能路由至各自的服务目的地,如S3,Lambda函数。另外方案中采用CloudFormation,创建CloudFormation模版来实现自动部署。

云端Web服务

对于那些出厂时并不知道需要连接哪个物联网云服务或者不能得到Bootstrap证书时,可以HTTPS来连接一个事先指定的Web服务,通过提供设备端设备的序列号、密码等信息来从Web服务中获取相关的IoT Endpoint URL,Bootstrap证书和私钥等信息。Web服务则需要从Amazon IoT云端获取到IoT Endpoint URL,Bootstrap证书和私钥等信息,这些可以通过调用Amazon IoT API的方式来获取。出于安全方面的考虑,AWS IoT不支持查询已有设备证书和私钥,只能在创建设备证书和私钥时得到证书和私钥。所以我们必须在创建设备证书和私钥时保存它们。具体的Python API接口如下:

  • 通过调用DescribeEndpoint来获取Amazon IoT的Endpoint URL地址。通过输入参数endpointType为iot:Data-ATS来获取IoT Endpoint URL信息。另外,也需要调用GetCallerIdentity来获取客户账号信息,用于在IoT Polidy中填写客户账户信息。
  • 通过调用CreateKeysAndCertificate来创建设备证书和私钥,并进行保存,后面将用于Bootstrap证书和私钥供设备端下载,从而供进一步的设备批量注册使用。输入参数中setAsActive 定义证书是否为激活状态,然后返回:certificateArn 证书ARN, certificateId证书ID, certificatePem证书具体内容, keyPair 密码对(包括私钥和公钥)。
  • 通过调用CreatePolicy来创建IoT策略,使得该Bootstrap证书只适用于设备注册之用。输入参数重policyName为IoT策略名称,返回的值则为policyArn IoT策略ARN,policyDocument IoT策略内容,policyName IoT策略名称,policyVersionId IoT策略版本ID等信息。然后通过调用AttachPolicy来添加IoT策略到设备证书,其输入参数为policyName IoT策略名称以及需要添加改IoT策略的target目标证书ID。绑定后,则使得该证书只能有该IoT策略,也即只能适用于设备注册之用。

示例代码如下,需要注意将相关的bootstrapPolicyDocument和AK/SK需要定义好响应的值。

import boto3

bootstrapPolicyDocument = 'xxxxxx'
bootstrapPolicyName = 'bootstrapPolicy'
provisioningTemplateName = 'testFleetTemplate'

client = boto3.client('iot', aws_access_key_id=access_key_id, aws_secret_access_key=secret_key, region_name='cn-north-1')
awsAccount = boto3.client('sts', aws_access_key_id=access_key_id, aws_secret_access_key=secret_key, region_name='cn-north-1').get_caller_identity().get('Account')
   
response_endpoint = client.describe_endpoint(endpointType='iot:Data-ATS')

response_keys_cert = client.create_keys_and_certificate(setAsActive=True)
bootstrapCertArn = response_keys_cert['certificateArn']
response_policy = client.create_policy(policyName=bootstrapPolicyName, policyDocument=bootstrapPolicyDocument)
response_attach_policy = client.attach_policy(policyName=bootstrapPolicyName, target=bootstrapCertArn)

云端设备自动注册服务

一般来说,设备端设备中事先并没有用于Amazom IoT Core 的设备证书。通过使用AWS IoT队列预置(Fleet Provisioning),IoT 设备将拥有由队列中其他设备共享的声明证书,AWS IoT 可以在设备首次连接到时使用设备的配置模板注册设备,生成设备证书和私有密钥,并在首次连接时将它们安全地传递到设备 AWS IoT。AWS IoT提供由 Amazon Root 证书颁发机构 (CA) 签发的客户端证书。

Amazon IoT 提供的设备 Fleet Provisioning自动注册的过程具体请参考https://aws.amazon.com/blogs/iot/how-to-automate-onboarding-of-iot-devices-to-aws-iot-core-at-scale-with-fleet-provisioning/ 。在这里,通过 CloudFormation 模版的方式,将Fleet Provisioning批量自动注册服务可以自动部署在云平台中。

CloudFormation 模版示例代码如下。需要注意事先把对应的fleet-provisioning-policy-name和FleetProvisioningRole创建好。

FleetProvisioningTemplate:
  Type: AWS::IoT::ProvisioningTemplate
  Properties: 
    Description: Fleet provisioning template
    Enabled: true      
    ProvisioningRoleArn: 
      Fn::GetAtt:
      - FleetProvisioningRole
      - Arn  
    TemplateBody: |
      {
        "Parameters": {
          "SerialNumber": {
            "Type": "String"
          },
          "AWS::IoT::Certificate::Id": {
            "Type": "String"
          }
        },
        "Resources": {            
          "certificate": {
            "Properties": {
              "CertificateId": {
                "Ref": "AWS::IoT::Certificate::Id"
              },
              "Status": "Active"
            },
            "Type": "AWS::IoT::Certificate"
          },
          "policy": {
            "Properties": {
              "PolicyName": "fleet-provisioning-policy-name"
            },
            "Type": "AWS::IoT::Policy"
          },
          "thing": {
            "OverrideSettings": {
              "AttributePayload": "MERGE",
              "ThingGroups": "DO_NOTHING",
              "ThingTypeName": "REPLACE"
            },
            "Properties": {
              "AttributePayload": {},
              "ThingGroups": [],
              "ThingName": {
                "Ref": "SerialNumber"                  
              }
            },
            "Type": "AWS::IoT::Thing"
          }
        }
      }

TemplateName: !Ref FleetProvisioningTemplateName

IoT规则定义和操作

Amazon IoT提供规则引擎用于数据路由。通过定义规则可以使设备能够与 AWS 相关服务进行交互。这些规则是基于 MQTT 主题流来进行规则的分析和执行,可以使用规则来支持如下任务:

  • 将文件保存到 Amazon S3
  • 调用 Lambda 函数来提取数据,将数据保存到RDS (SQL Server)或ElastiCache (Redis)数据库中

数据路由至S3

Amazon IoT规则操作中的S3 (s3) 操作将数据从 MQTT 消息写入 Amazon Simple Storage Service (Amazon S3) 存储桶。

  • 创建一个S3存储桶供数据存储之用
  • 创建一个规则操作将收取到的相关MQTT主题的数据消息保存至S3存储桶中

CloudFormation模版示例代码如下,需要注意实现需要将S3存储桶创建好。

  S3TopicRule:
    Type: AWS::IoT::TopicRule
    Properties:
      RuleName: RuleToS3
      TopicRulePayload:
        RuleDisabled: false
        Sql: !Join [ "", [ "SELECT * AS payload, topic(1) AS deviceName, FROM '", !Ref S3RuleTopic, "/#'"] ]
        Actions:
        - S3:
            BucketName:
              Ref: S3BucketName
            RoleArn:
              Fn::GetAtt:
              - S3Role
              - Arn
            Key: ${topic()}/${timestamp()}

数据路由至Lambda处理和数据存储至RDS (SQL Server)或ElastiCache (Redis)数据库中

Amazon IoT规则操作中的Lambda (lambda) 操作调用 AWS Lambda 函数,传入 MQTT 消息。 AWS IoT 异步调用 Lambda 函数。Lambda函数将处理从IoT Core中路由过来的数据然后对数据进行处理,最后将相关数据存储到对应的RDS (SQL Server)或ElastiCache (Redis)数据库中供应用系统进行进一步的数据显示和处理。

  • 创建一个Lambda函数,用于将相关数据保存至RDS (SQL Server)或ElastiCache (Redis)数据库中。Lambda函数的一些变量在调用模版时输入相关参数。
  • 创建一个规则操作将收取到的相关MQTT主题的数据消息路由至Lambda函数进行操作处理,Lambda函数对这些数据进行处理并保存至RDS (SQL Server)或ElastiCache (Redis)数据库中。
  • 编写Lambda函数:在这里,设备传感器发送的内容包括MQTT主题名和JSON数据,通过IoT规则引擎的Lambda规则操作对之进行解释,并将对应的数据存储到特定的SQL Server数据库的table中。RDS (SQL Server)或ElastiCache (Redis)实例地址和端口号将由Lambda的变量在部署CloudFormation模版时输入参数。

CloudFormation 模版的示例代码如下,需要注意将对应的Lambda创建好。在访问SQL Server时,可以用pyodbc,作为Lambda的Layer进行添加。在访问Redis中,则需要将python的redis库添加到代码中。

SqlServerLambdaTopicRule:
    Type: AWS::IoT::TopicRule
    Properties:
      RuleName: RuleToSqlServerLambda
      TopicRulePayload:
        RuleDisabled: false
        Sql: !Join [ "", [ "SELECT * AS payload, topic(1) AS deviceName, FROM '", !Ref S3RuleTopic, "/keydata/#'"] ]
        Actions:
          - Lambda:
              FunctionArn: !GetAtt SqlServerLambdaFunction.Arn

自动部署

AWS CloudFormation 是一项服务,可帮助对 AMS 资源进行建模和设置,以便能花较少的时间管理这些资源,而将更多的时间花在运行于 AWS 中的应用程序上。CloudFormatin支持创建一个描述所需的所有 AWS 资源(如Amazon IoT Core、Amazon S3存储桶或 Amazon Lambda)的模板,并且 CloudFormation 将负责设置和配置这些资源。在本博文中,将提供CloudFormation模版,Web服务通过API调用来将CloudFormation模版部署到Amazon云平台中。在模版中,提供了如下资源:

  • IoT 证书、策略、物件操作
  • S3 存储桶
  • Lambda 函数
  • IoT 规则定义和操作
  • IAM 角色定义

物联网设备端设计

在设备端主要包括两方面,一方面需获得设备端设备与Amazon IoT 云端安全连接的必要信息然后自动注册到云端,从而实现设备与云端的安全连接。另一方面需要将设备采集到的数据经过处理然后发送至Amazon IoT云端。

设备自动注册

在云端提供设备自动注册服务后,需要在设备端设备发送数据之前,获取到设备端设备连接Amazon IoT Core 所需要的必要信息,比如 IoT Endpoint URL,Bootstrap 设备证书和私钥。考虑到在设备端设备交付给客户之前,可能这些客户的账户还没有创建完毕。所以在设备端设备上会统一向 Web 服务来查询这些信息。

  • 根据设备 MAC 地址连接 EC2 上的 Web 服务来获取 IoT Endpoint URL,Bootstrap设备证书和私钥等信息
  • 调用Fleet Provisioning客户端程序与Amazon IoT Core交互来获取真正可用的设备证书和私钥。这里可以重用https://github.com/aws-samples/aws-iot-fleet-provisioning 里面的代码来实现设备与Amazon IoT Fleet Provisioning的通信。

设备数据读取和发送

设备端设备与Amazon IoT 云端建立安全连接后,将设备采集到的信息进行处理,然后将这些JSON数据发送到Amazon IoT 云端。在这里,数据发送到Amazon IoT 云端则可以用AWS IoT Device SDK for Python,采用MQTT publish 的方式来发送数据至 IoT 云端。

  • 从设备端本地将采集到的数据进行处理成JSON数据,JSON数据里面包括了多个时间戳及其对应传感器数值。
  • 基于获取的设备证书和私钥与 Amazon IoT Core 建立安全连接,将读取到的 JSON 数据发送(MQTT Publish)到IoT Core中。MQTT 的发送主题包括了一下设备信息和传感器信息供后续Amazon IoT 规则引擎来进行分析和处理等等。示例例子可以参考AWS IoT Device SDK for Python里面的例子,如basicPubSub.py文件。

总结

通过本博文,成功的解决了包括工业物联网、智能家居等行业中存在的三个问题。第一,解决大量设备上线和自动注册的问题,即使在设备出厂前都不知道会连接哪个物联网平台。第二,通过规则引擎,根据消息主题将不同的数据路由至不同的存储系统,供进一步的数据程序和处理。第三,通过CloudFormation模版,将云端服务通过CloudFormation模版能自动部署到云平台中,使得云服务能快速得到部署和复制。这样,在设备端通过使用现有的AWS IoT Device SDK及其示例能很好的将设备注册到云端,与云端建立安全连接,然后将数据发送到云端进行进一步的处理。

本篇作者

张守武

亚马逊云科技专业服务团队物联网顾问。负责基于亚马逊云科技 IoT 的解决方案咨询和项目交付,同时负责物联网行业解决方案的开发和推广,在物联网、网络、视频等领域有着广泛的设计和实践经验。

高业坤

亚马逊云科技专业服务团队IoT架构师。负责基于亚马逊云科技 IoT的解决方案咨询,架构与交付,深度参与过智慧工厂、智慧供热等行业的IoT解决方案的咨询与交付。在智能家居、智慧安防、智能硬件等IoT行业拥有十年以上软件研发管理经验。

杨阳

亚马逊云科技专业服务团队物联网应用架构师。负责基于亚马逊云科技 IoT的解决方案咨询,架构与交付,深度参与过智慧工厂、智能家居等行业的IoT解决方案的咨询与交付。进入亚马逊云科技之前在消费电子产品和制造业拥有丰富的物联网项目开发和管理经验。