DIY 火星探测器:AWS Greengrass IoT v2 与 Raspberry Pi(第一部分)。





5.00/5 (3投票s)
在本系列的两部分中,您将学习如何使用 AWS Greengrass v2 将树莓派变成一个灵活且强大的物联网设备,最终创建一个离网的远程任务数据和图像收集设备。
- 下载源码 - 78 Kb
- GitHub 项目
- ACG 项目:DIY 火星探测器 (需要免费账户)
引言
在这个为期两部分的课程中,我们将探索 AWS Greengrass 和物联网设备。具体来说,我们将把下面的零件组合成一个离网的远程控制图像和数据收集设备。我们将使用树莓派 Zero、一个 Pi 相机、一个蜂窝调制解调器以及其他一些组件,并结合 AWS Greengrass 版本 2。Greengrass 版本 2 于 2020 年底发布,虽然 AWS 仍然支持 Greengrass v1(他们现在称之为“经典版”),但他们鼓励新项目使用版本 2 路径……而我们也将走这条路。
没有 Pi?没问题。在第一部分中,我们将使用 EC2 实例作为 Pi 的替代品,来理解 Greengrass v2 的基本知识以及如何构建和部署自定义组件。在本项目的第二部分,我们将重点关注 Pi 版本。对于我们的物理设备,我将使用一个树莓派 Zero,由锂离子电池组和太阳能电池板供电。我们将通过蜂窝调制解调器(在 Pi 世界中称为 cellular hat)将其连接到互联网。然后,我会把所有这些东西塞进一个防水盒里,看看它能在野外在线多久。
如果您想观看本教程的配套视频,请前往 A Cloud Guru 的 ACG Projects 主页。在那里,您会找到本教程和其他动手教程,这些教程旨在帮助您在学习的同时进行实践。观看视频需要免费账户,但有了这个免费账户,您每月还将获得精选的免费课程和其他不错的优惠……免费!
完全可能的情景
好吧,我有个好消息和一个坏消息。好消息是我们崭露头角的太空初创公司刚刚赢得了一份利润丰厚的合同,要在火星上建造和维护一个传感器集群!坏消息是,我们计划的绝大部分预算将用于将设备实际发射到红色星球并着陆。我们的任务是以低成本构建一个设备管理和数据收集系统。要求是:
- 根据要求,设备需要捕获一张照片,收集环境读数并将结果存储在云端。
- 由于到火星的数据连接非常不稳定,该解决方案需要适应间歇性连接。
- 必须自带动力。
好了,好了……在所有太空爱好者开始挑剔这个前提之前,我想请你们暂时搁置一下怀疑。是的,我相信太空辐射会摧毁我们的现成组件,虽然我将使用蜂窝调制解调器进行连接,但我相当确定火星上还没有 5G 数据网络。说实话,我们也不是一个崭露头角的太空初创公司,对吧?但是请记住,当我们还是孩子玩过家家的时候,我们的想象力里什么都有可能发生。让我们回到那个地方一会儿。
架构
对于我们的架构,我们将使用 AWS Greengrass 作为我们的控制平面和数据平面。我们将为我们的树莓派(或我们的假 Pi EC2 实例)配备所需的组件,将它们变成 Greengrass 所称的“核心设备”。核心设备本身可以充当数据收集点,也可以充当其他设备的本地代理……有点像一个收集点或网关,连接回 Greengrass。
为了与我们的核心设备通信,我们将使用 MQTT。MQTT 是一种轻量级的消息协议,广泛用于物联网应用。如果您熟悉其他消息队列设计模式,那么 MQTT 对您来说会很熟悉。它的队列称为主题,设备可以订阅和发布到主题以发送和接收消息。这就是我们将指令发送到我们的传感器并获得响应的方式。我们还将让设备将捕获的图像上传到 S3 存储桶。
用 EC2 模拟
让我们开始吧。此项目将通过两种方式完成……第一部分将使用 EC2 实例,适用于没有树莓派的人。第二种方式将使用树莓派 Zero。对于 EC2 版本,我们将使用 T4g.nano
ARM64 实例,运行 Debian 10,这对于树莓派 3 或 4 是一个不错的替代品。对于树莓派 Zero,它使用 ARM6 架构,内存占用非常小,因此需要进行一些特殊的处理。
准备好我们的 FakePi
我们可以通过启动一个 T4g.nano EC2 实例并通过 SSH 连接到该实例来开始。请注意,对于 Debian 10 AMI,默认用户帐户是 admin
,而不是您可能习惯使用的 ec2-user
或 ubuntu
用户。登录后,执行一些更新并安装一些我们需要的依赖项。
$ sudo apt update && sudo apt upgrade -y && sudo reboot $ sudo apt install unzip default-jdk-headless python3-pip cmake -y
Greengrass 准备工作
在安装的同时,让我们做些其他工作。
- 创建一个 S3 存储桶。此存储桶将用于托管我们的 Greengrass 自定义组件工件以及我们的探测器捕获的数据。注意:请确保在您计划使用 Greengrass 的区域创建存储桶……这将为您节省一些故障排除的时间。
- 为引导创建 IAM 策略。由于我们将使用 Greengrass 的自动配置功能,因此我们需要创建一个策略,允许我们的设备有足够的访问权限来自行配置。我将把此策略命名为
customGreengrassProvisionPolicy
,我们需要在 AWS 文档中使用最少的必需权限。 - 创建 IAM 策略以允许访问我们的 S3 存储桶。由于我们需要我们的设备能够从我们上面创建的 S3 存储桶获取和放置数据,因此我们需要明确地将此权限授予将在配置过程中创建的 Greengrass IAM 角色。我将把此策略命名为
customGreengrassS3Access
。{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:PutObjectAcl" ], "Resource": "arn:aws:s3:::_your_bucket_here_/*" } ] }
- 创建一个将用于自动配置的 IAM 用户帐户。我们只需要此用户帐户的访问密钥和密钥,稍后使用。我们还需要将上面创建的
customGreengrassProvisionPolicy
分配给此用户帐户。
准备好 Greengrass-ed
此时,您的 EC2 实例应该已准备就绪。如果尚未登录,请通过 SSH 重新登录。从 AWS 控制台,导航到 AWS IoT,然后到 Greengrass 部分。选择核心设备,然后选择设置一个核心设备。
接下来会显示一个设置屏幕。添加我们预期的设备名称,我们可以选择一个现有设备组,创建一个新组,或者不将此设备分配给任何组。我们将我们的设备命名为 FakePi
,并创建一个名为 MarsProbes
的组。组很重要,因为我们可以将组件部署到组,并且该组中的所有设备都将获得相同的部署……如果您处理成千上万个设备,这会非常方便。
控制台将生成两条命令行供您使用:一条用于下载和解压 Greengrass 核心元素,另一条用于安装和配置设备。最终,我们只需将这些命令行复制并粘贴到我们的实例中并执行。在执行此操作之前,我们需要启用我们的实例以连接到 AWS 并执行操作。这就是我们 GreengrassBootstrap
用户提供的访问密钥和密钥发挥作用的地方。
现在,AWS 会告诉您更好的方法是使用 STS 生成临时凭证并承担我们设置的配置角色。或者,您可以像我下面那样直接将它们设置为环境变量……最终,您只是想获得一个可以导出为环境变量的访问密钥和密钥。这些不会被 Greengrass 安装保存,并且在下次注销或重启时会消失,因此这是一项风险很低的活动。
$ export AWS_ACCESS_KEY_ID = _your_access_key_from_the_GreengrassBootstrap_user $ export AWS_SECRET_ACCESS_KEY = _your_secret_from_the_GreengrassBootstrap_user
复制并粘贴这两行并执行。Greengrass 安装后,几分钟后您应该会在控制台的 Greengrass 核心设备下看到它。您现在正式拥有了一个已连接到 AWS 的 Greengrass IoT 核心设备。
我们的第一次部署
现在,由于我们的设备内存有限,我们将需要调整默认的 Greengrass 设置,使其运行更顺畅。您可以跳过此步骤,但当 JVM 使用掉微薄的内存时,您可能会遇到大量的交换,这会大大降低速度。要进行此调整,我们需要修改我们的部署,以便它向设备发送特定的 JVM 配置。我们将设置的组件称为 aws.greengrass.Nucleus
。从 Greengrass 控制台,选择部署,然后选择包含我们设备的部署……在我们的例子中是MarsProbes 的部署。
进入部署后,点击修订。进入“修订部署”向导后,点击“下一步”到达选择组件屏幕。我们将通过转到公共组件列表并搜索 aws.greengrass.Nucleus
组件并勾选它来定制此部署。继续进行“修订部署”向导的第 3 步,我们选择 aws.greengrass.Nucleus
旁边的单选按钮,然后点击配置组件。
您将看到一个屏幕,我们可以在其中将自定义配置与 AWS 提供的公共组件合并。您会在屏幕的左侧看到默认配置。我们需要在屏幕的右侧添加一些额外的 JVM 选项。 这段配置是针对内存占用减少推荐的配置。AWS 文档中有一个绝对最小版本,但我尝试使用该版本时遇到了错误。这个简化的配置似乎效果很好。将缩减的内存分配设置复制并粘贴到要合并的配置部分。
继续完成向导,直到到达部署屏幕,然后点击部署。Greengrass 将立即开始将配置更改部署到您的 Greengrass 设备……或在我们的例子中是设备。您可以在控制台中或在设备上通过查看 top
中的 Java 进程来监视部署进度,也可以查看 Greengrass 日志。
$ sudo tail -F /greengrass/v2/logs/greengrass.log
在日志活动看起来平静下来并且部署状态在部署控制台页面上更改为“已完成”之后,我们就部署了新的内存设置。现在,为了以防万一,我更喜欢在更改内存后重启我的设备。我遇到过一些情况,即使重启 Greengrass 服务后,更改也没有生效。重启似乎能解决问题。
我们的第一个(自定义)部署
接下来,我们准备构建我们的自定义组件。对于这个 EC2 示例,我创建了一个简单的 Python 程序 artifacts/simpleSubPub/1.0.0/simpleSubPub.py,它使用 AWS IoT SDK 监听一个主题,并在该主题上出现内容时做出响应。Greengrass 组件分为两部分——工件和配方。工件是实际代码和任何相关的库。配方以 JSON 或 YAML 格式构建,描述了我们的组件需要安装和启动的所有依赖项、访问权限和工件。
我在 simpleSubPub.py 程序中添加了大量注释,所以这里不再详细介绍。需要注意的一点是文件夹和命名约定——似乎 遵循 artifacts/componentName/componentVersion/ 格式很重要。AWS 已记录了配方格式,但请花一点时间逐步了解 recipes/simpleSubPub-1.0.0.json 文件,以便熟悉其中的各个部分。
在配方中,生命周期部分值得关注。这一部分将告诉 Greengrass 如何安装和运行我们的 Python 代码。在我们的例子中,我们需要使用 PIP 安装一些依赖项,而 Run 属性包含了启动程序的 Shell 命令。请注意 PIP 上的 --user
参数以及 python Shell 命令上的 -u
……我们的 Greengrass 进程将以配置过程中创建的特殊 Greengrass 用户帐户 ggc_user
运行。我们想确保依赖项和 Python 是在该用户的作用域内运行的。在故障排除时,这一点很重要……您可能需要将 ggc_user 添加到本地设备组或授予某些文件系统权限。有一种方法可以让 Greengrass 以 root 用户身份运行组件,但这通常是个坏主意,并且违反了最小权限原则。
现在我们需要将我们的工件(即我们的 simpleSubPub.py 文件)复制到我们的 S3 存储桶。我们可以通过控制台或 AWS CLI 来完成,如下所示:
$ aws s3 cp --recursive (local-path-to-repo)/artifacts/ s3://_your_bucket_here_/artifacts/
如果我们有不止一个 Python 文件,我们需要将它们压缩成一个存档,并将该存档文件复制到 S3 中正确的位置,同时遵循所需的命名和目录约定。请注意,使用存档文件需要在配方中的 Manifests 部分使用略有不同的格式,这在AWS 文档中有介绍。
一旦我们将工件复制到 S3,我们就需要确保我们的 Greengrass 进程在部署时能够实际访问 S3 存储桶以下载工件。我们可以通过将我们之前创建的 customGreengrassS3Access
策略添加到在配置过程中为 Greengrass 设备创建的 GreengrassV2TokenExchangeRoleAlias
角色来实现。设备不直接使用此角色,而是您可能在配方中注意到的依赖项 aws.greengrass.TokenExchangeService
使用此角色来生成临时令牌,以便我们的设备访问 AWS 服务。我们在 GreengrassV2TokenExchangeRoleAlias
角色中放置的内容决定了我们的设备可以在 AWS 上访问什么。
从 AWS IoT 控制台,我们可以进入安全,然后进入角色别名。我们应该会看到 GreengrassV2TokenExchangeRoleAlias
角色。点击该角色,我们将进入一个屏幕,该屏幕会将我们带到 IAM 以便我们编辑该角色。我们将 customGreengrassS3Access
策略附加到该角色,现在我们的设备就可以读取和写入我们的 S3 存储桶了。
现在一切都就绪了。从 Greengrass 控制台,选择组件,然后选择创建组件。在这里,我们粘贴我们刚刚创建的 JSON 或 YAML 配方。我们的 JSON 文件应包含 AWS 准备部署您的组件所需的一切。然后我们可以点击部署,系统会询问我们是否要将其添加到现有部署或创建新部署。让我们将其添加到我们现有的部署中。继续完成屏幕,我们将看到我们的新组件在“我的组件”下,而我们现有的自定义 Nucleus 组件在“公共组件”下。我们希望保留后者,否则 Greengrass 将认为我们要从核心设备中删除 Nucleus,这会很糟糕。下一步,下一步,下一步,然后部署。
与上次相同的情景……您可以从 greengrass.log 中查看部署,还可以通过查看部署进行到一定程度后立即创建的 simpleSubPub.log 文件来查看正在部署的组件。
$ sudo tail -F /greengrass/v2/logs/simpleSubPub.log
如果您查看部署,您会注意到它们也有版本。您可以修订部署以设置新参数或自定义项,也可以添加和删除组件。如果我想删除 simplePubSub 组件,我可以修订我的部署并取消选中该组件。然后它将被删除。那么,如果您的设备离线会怎样?嗯,这是 Greengrass 的优势……它旨在与连接性间歇的设备配合使用。下次您的设备连接到 AWS 时,它将接收其指令集并执行所需的操作。您可以通过停止 EC2 实例,设置部署,然后在未来某个时候将其重新启动来测试这一点。MQTT 消息也是如此,我们稍后会在 Pi Zero 路径中看到。
我们模拟了……我们成功了吗?
一旦设备上的活动平静下来,并且您的部署控制台页面显示部署已完成,我们就可以进行测试了。(注意:我遇到过部署卡在“活动”状态的情况,尽管所有迹象似乎都表明部署已成功完成。我只是忽略了这些情况,继续进行了。)从 IoT 控制台,我们可以进入测试部分,然后点击MQTT 测试客户端。首先,让我们订阅一些主题……也许是所有主题,这样我们就可以看到一切。我们在主题过滤器中输入 #
。现在,我们可以将消息发送到我们的 Python 代码正在监听的主题……在发布到主题选项卡上,我们输入 marsprobes/request
并输入一些消息。如果一切正常,我们将会收到一个响应,其中包含组件放置在 S3 上的文件的 URL。大家一起庆祝!
What Next?
如果您想体验完整的 Pi 体验,您可以直接继续第二部分。有关本次完整教程的视频版本,请前往 A Cloud Guru 的 ACG Projects 页面。观看视频需要免费账户,但有了这个免费账户,您每月还将获得精选的免费课程和其他不错的优惠……免费!