基於 OpenWrt 作業系統下運行 AWS IoT GreenGrass Version 2
- 作者 -
詹東恩 (Tec Chan)
AWS IoT Solutions Architect
CPU 架構 | 作業系統 |
Armv7l | Linux |
Armv8(AArch64) | Linux |
x86_64 | Linux |
下圖演示 AWS IoT Greengrass 的裝置是如何與 AWS IoT Greengrass 雲端服務以及其他 AWS 服務的互動。
而在廣大的嵌入式作業系統中,OpenWrt 是一個適合用於嵌入式裝置的一個 Linux 發行版本,目前市面上許多的嵌入式硬體平台皆採用以 OpenWrt 作為其基礎,例如路由器(Network Router)、網路閘道(Network Gateway)或工業用電腦,藉由在 OpenWrt 上運行 AWS IoT Greengrass Version 2,將使其在雲端上強大的功能帶至邊緣端設備。由於目前 AWS IoT Greengrass Version 2 尚未正式支援OpenWrt 上的運行,在本文中我將向您說明如何基於在 OpenWrt 作業系統下運行 AWS IoT Greengrass Version 2,並透過範例演示 AWS IoT Greengrass Version 2 強大的功能,其中搭配使用的硬體平台為 Raspberry Pi 4。
先決條件與事前準備- 一台可以進行 OpenWrt 原始碼編譯的個人電腦或筆記型電腦,建議搭配 Ubuntu 18.04 或較新的 Linux 作業系統版本,本文採用的是Ubuntu 18.04。
- 一個註冊的 AWS 帳號,可參考此鏈結進行 AWS 帳號申請,每個 AWS 帳號皆有提供相關服務的免費額度,關於服務免費額度的相關訊息可參考此鏈結。
- 一個 Raspberry Pi 4 硬體開發平台。
- 選項:AWS Command Line Interface(AWS CLI),可以讓您使用命令列的方式來使用 AWS 相關服務,請參考此鏈結在適合您的作業系統環境下安裝 AWS CLI。
-
登入建置 OpenWrt 的個人電腦或筆記型電腦,執行系統更新與安裝編譯所需之軟體。
$sudo apt update
$sudo apt install build-essential ccache ecj fastjar file g++ gawk gettext git java-propose-classpath libelf-dev libncurses5-dev libncursesw5-dev libssl-dev python python2.7-dev python3 unzip wget python3-distutils python3-setuptools rsync subversion swig time xsltproc zlib1g-dev -
下載 OpenWrt 原始碼,並進行環境設置,您可以從此鏈結下載編譯 OpenWrt 時所需要用到的組態檔。
#下載OpenWrt原始碼
$cd ~
$mkdir workspace && cd workspace
$git clone https://git.openwrt.org/openwrt/openwrt.git
$cd ~/workspace/openwrt
#更新並安裝OpenWrt相關之組件
$./scripts/feeds update -a
$./scripts/feeds install -a
#安裝python3所需要的組件,在後面的範例程式中會使用到
$./scripts/feeds install python3 -
複製下載的組態檔至OpenWrt的根目錄,並進行組態檔的載入。
$cd ~/workspace/openwrt
#/path/to/ 為您下載範例組態檔的路徑
$cp /path/to/openwrt.config .config
#設定編譯OpenWrt相關參數
$make menuconfig按照下列圖示,進行組態檔的載入。
-
在載入 OpenWrt 組態檔之後進行編譯,視您的機器能力不同,編譯的時間需數十分鐘不等。
$cd ~/workspace/openwrt/
#若編譯途中產生錯誤,請移除-j$(nproc)進行除錯
$make -j$(nproc) V=s -
若編譯完成並沒有產生任何錯誤,您可以在此目錄下找到 openwrt-bcm27xx-bcm2711-rpi-4-squashfs-factory.img.gz。
$cd ~/workspace/openwrt/bin/targets/bcm27xx/bcm2711-glibc/
$ls
config.buildinfo openwrt-bcm27xx-bcm2711-rpi-4-squashfs-factory.img.gz profiles.json
feeds.buildinfo openwrt-bcm27xx-bcm2711-rpi-4-squashfs-sysupgrade.img.gz sha256sums
openwrt-bcm27xx-bcm2711-rpi-4-ext4-factory.img.gz openwrt-bcm27xx-bcm2711-rpi-4.manifest version.buildinfo
openwrt-bcm27xx-bcm2711-rpi-4-ext4-sysupgrade.img.gz packages -
準備一個空的 SD card,建議容量大於 32GB,在本文中我們使用的是 balenaEtcher 來進行映像檔的刷入,您可以從此鏈結下載 balenaEtcher。
-
請參照下列指令與設定進行 OpenWrt 上的網路介面設定。
#cd /etc/config
#vi network在此檔案最後加入下列兩行設定,儲存並離開。
config interface 'wan'
option proto 'dhcp' -
本文在 Raspberry Pi 4 使用無線網路來存取網際網路的資源,請參照下列指令與設定進行 OpenWrt 上的無線網路設定。
#cd /etc/config
#vi wireless在此檔案上註記掉原本的無線網路設定,並根據您的無線網路環境增加設定。
#請根據您的無線網路環境修改channel, band與htmode參數
config wifi-device 'radio0'
option type 'mac80211'
option path 'platform/soc/fe300000.mmcnr/mmc_host/mmc1/mmc1:0001/mmc1:0001:1'
option channel '11'
option band '11g'
option htmode 'HT20'
option disabled '0'#您可以選擇註記或刪除下列原始的無線網路設定
#config wifi-iface 'default_radio0'
#option device 'radio0'
#option network 'lan'
#option mode 'ap'
#option ssid 'OpenWrt'
#option encryption 'none'#請根據您的無線網路環境修改your_ap_ssid與your_wifi_password,其中your_ap_ssid是您的無線網路AP SSID,your_wifi_password是您的無線網路密碼
config wifi-iface
option mode 'sta'
option device 'radio0'
option network 'wan'
option ssid 'your_ap_ssid'
option encryption 'psk2'
option key 'your_wifi_password' -
當您設置完網路介面與無線網路之後,重啟 OpenWrt 的網路服務使其生效。
#service network restart
#ping www.amazon.com
PING www.amazon.com (23.208.81.175) 56(84) bytes of data.
64 bytes from 23.208.81.175: icmp_seq=1 ttl=117 time=60.8 ms
64 bytes from 23.208.81.175: icmp_seq=2 ttl=117 time=61.5 ms
64 bytes from 23.208.81.175: icmp_seq=3 ttl=117 time=61.4 ms -
為了方便遠端操作 OpenWrt,本文建議開啟 ssh 遠端登入,由於 OpenWrt 預設會開啟防火牆,在本文中我們會先行關閉防火牆進行遠端的登入,在運行本文中的範例之後,請您根據您原有的防火牆設定再次開啟防火牆。
#service firewall stop
-
透過遠端機器建立 ssh 連線連至您的 OpenWrt,本文中使用 putty 來進行 ssh 連線,您可以從此鏈結下載 putty。
$ssh root@your_rpi_ip
其中參數 your_rpi_ip 可以在 OpenWrt 內使用下列指令獲取。
#ifconfig wlan0
wlan0: Link encap: Ethernet HWaddr xx:xx:xx:xx:xx:xx
inet 172.20.10.2 netmask 255.255.255.240 broadcast 172.20.10.15
inet6 addr 2001:b011:200f:2234:b04d:63cd:bdc4:15a8/64 Scope:Link
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions登入之後的畫面會如下,其中 OpenWrt 的版本號會根據您當下所下載的原始碼不同而異。
-
由於 AWS IoT Greengrass Version 2 為 JAVA的rumtime,在此需要下載 JDK 的環境以便後續運行 AWS IoT Greengrass Version 2,本文使用的 JDK 為 Amazon Corretto 11,請參考下列的指令下載並設定 JAVA 環境變數。
#cd ~
#curl -LO https://corretto.aws/downloads/latest/amazon-corretto-11-aarch64-linux-jdk.tar.gz
#tar zxvf amazon-corretto-11-aarch64-linux-jdk.tar.gz
#mv amazon-corretto-11.0.12.7.1-linux-aarch64 openjdk-11
#export JAVA_HOME="/root/openjdk-11"
#export PATH=$PATH:$JAVA_HOME/bin
#java -version運行之後您將會看到如下圖所示 Amazon Corretto 11 資訊,其中 Amazon Corretto 11 的版本號會根據您當下所下載的檔案不同而異。
-
您也可以將 JAVA 的參數寫入以下檔案,重新登入後使其永久生效。
#vi /etc/profile
於此檔案新增以下兩行
export JAVA_HOME="/root/openjdk-11"
export PATH=$PATH:$JAVA_HOME/bin
AWS IoT Greengrass Version 2
-
登入您的 AWS 控制台,搜尋 IoT Core 服務並點擊進入。
登入 IoT Core 控制台後會如下圖所示。
-
若您登入後的主控台沒有顯示左手邊相關服務資訊列,請點擊左上方三條槓圖示以便展開。
-
點擊 Greengrass 展開服務,選擇 Getting started 之後在畫面右方點擊 Set up one core device。
-
在 Core device name 的欄位中輸入您想要的名稱,或者您可以選擇使用系統預設值。
-
在 Thing group 中點選 Enter a new group name 並輸入您想要的群組名稱,或者您可以選擇使用系統預設值。
-
往下捲動至 Run the installer,點選 Copy 並記錄下此行指令,在後續的步驟將會使用到此指令。
-
點擊 View core devices。
-
登入您的 OpenWrt,參考下列命令設定您的 AWS 存取金鑰與秘密金鑰。
#export AWS_ACCESS_KEY_ID=your_aws_access_key_id
#export AWS_SECRET_ACCESS_KEY=your_aws_secret_access_id -
下載 AWS IoT Greengrass Version 2 最新版本,其中 AWS IoT Greengrass Version 2 的版本號會根據您當下所下載的檔案不同而異。
#cd ~/
#curl -s https://d2s8p88vqu9w66.cloudfront.net/releases/greengrass-nucleus-latest.zip > greengrass-nucleus-latest.zip && unzip greengrass-nucleus-latest.zip -d GreengrassCore
#java -jar ./GreengrassCore/lib/Greengrass.jar --version
AWS Greengrass v2.5.0 -
從雲端開始部署安裝 AWS IoT Greengrass Version 2。請複製前面在 AWS IoT 控制台上的命令列,並修改成如下列範例開始進行部署。
#cd ~/
##參數說明
##sudo -E:移除此參數,本文已經使用root權限登入OpenWrt
##--aws-region:請參考您所選取的AWS服務區域
##--thing-name:請參考您在上面章節所命名的AWS IoT Greengrass Core Name
##--thing-group-name:請參考您在上面章節所命名的AWS IoT Greengrass Group Name
##--setup-system-service:移除此參數,目前OpenWrt不支援
##--component-default-user:修改成root
##--provision:進行部署
##--deploy-dev-tools:進行額外AWS IoT Greengrass Command Line tools的部署
#java -Droot="/greengrass/v2" -Dlog.store=FILE -jar ./GreengrassCore/lib/Greengrass.jar --aws-region your_aws_region --thing-name your_greengrass_core_name --thing-group-name your_greengrass_group_name --component-default-user root:root --provision true --deploy-dev-tools true當您成功部署與運行 AWS IoT Greengrass Version 2 之後,您應該會在終端畫面上看到如下圖所示的訊息。
-
檢查您是否成功運行 AWS IoT Greengrass Version 2,請您參考下列的命令列,若尚未看到 greengrass-cli,請稍等片刻在進行測試。
#cd /greengrass/v2/bin
#./greengrass-cli -h當您成功部署並執行了 greengrass-cli 之後,您應該會在終端畫面上看到如下圖所示的訊息。
-
透過遠端機器建立 ssh 連線連至您的 OpenWrt,參考下列的命令列建置 artifact 的資料夾與 python 範例程式。
##請注意資料夾與範例程式的路徑,皆以前面章節為基礎,您可以按照您的需求修改位置
#mkdir -p /root/GreengrassCore/artifacts/com.example.HelloWorld/1.0.0 && touch /root/GreengrassCore/artifacts/com.example.HelloWorld/1.0.0/hello_world.py
-
使用編輯器開啟範例程式,並將以下範例程式碼貼上並儲存離開,此時範例程式應為空的內容。
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
import sys
import datetime
import time while True:
message = f"Hello, {sys.argv[1]}! Current time: {str(datetime.datetime.now())}."
# Print the message to stdout.
print(message)
# Append the message to the log file
with open('/tmp/Greengrass_HelloWorld.log', 'a') as f:
print(message, file=f)time.sleep(1)
-
參考下列的命令創建您元件的範例食譜(recipe),此例子使用的是 JSON 格式,您也可以使用 YAML 格式來撰寫您的食譜。
##請注意資料夾與範例程式的路徑,皆以前面章節為基礎,您可以按照您的需求修改位置
#mkdir -p /root/GreengrassCore/recipes && touch /root/GreengrassCore/recipes/com.example.HelloWorld-1.0.0.json
-
使用編輯器開啟範例食譜,並將以下範例內容貼上並儲存離開,此時範例食譜應為空的內容。
{
"RecipeFormatVersion": "2020-01-25",
"ComponentName": "com.example.HelloWorld",
"ComponentVersion": "1.0.0",
"ComponentDescription": "My first AWS IoT Greengrass component.",
"ComponentPublisher": "Amazon",
"ComponentConfiguration": {
"DefaultConfiguration": {
"Message": "world"
}
},
"Manifests": [
{
"Platform": {
"os": "linux"
},
"Lifecycle": {
"Run": "python3 -u {artifacts:path}/hello_world.py
'{configuration:/Message}'\n"
}
}
]
} -
運行與測試您的元件,以下建議您開啟多個終端連線至 OpenWrt,以利於您觀察範例的運行。
##請注意資料夾與範例程式的路徑,皆以前面章節為基礎,您可以按照您的需求修改位置
##開啟並監看AWS Greengrass Version 2日誌
#tail -F /greengrass/v2/logs/greengrass.log -
登入另一個終端連線至 OpenWrt,參考以下的命令透過 Greengrass CLI 從裝置端發起部署元件。
##請注意資料夾與範例程式的路徑,皆以前面章節為基礎,您可以按照您的需求修改位置
#/greengrass/v2/bin/greengrass-cli deployment create --recipeDir /root/GreengrassCore/recipes --artifactDir /root/GreengrassCore/artifacts --merge "com.example.HelloWorld=1.0.0"當您看到類似以下的訊息,代表此元件的部署已完成
-
參考以下的命令觀看此元件的日誌。
##範例python程式hello_world.py會持續列印訊息輸出至/tmp/Greengrass_HelloWorld.log
#tail - F /tmp/Greengrass_HelloWorld.log當您看到類似以下的訊息,代表此範例元件已成功部署並運行。
-
登入您已經安裝好 AWS CLI 命令列的機器,確保您可以使用 AWS CLI 命令列,您可以參考此鏈結設定您的 AWS CLI。請參考下列指令來設定您的 AWS CLI。
$aws configure
並於提示下輸入您 AWS 帳號的訊息,畫面如下。其中 AWS Access Key ID 與A WS Secret Access Key 請參考先前的章節,Default region name 則是輸入您所使用 AWS 服務的服務區。
-
請參考下列的命令創建 Amazon S3 的儲存貯體(bucket)並賦予儲存貯體名稱。
#您可以按照您的需求給予儲存貯體名稱
$EPOCH_TIME=$(date -d '06/12/2021 07:21:22' +"%s") && S3_BUCKET=ggcv2-sample-bucket-$HOSTNAME-$EPOCH_TIME && aws s3 mb s3://$S3_BUCKET -
登入您的 OpenWrt 並修改前面章節創立的食譜。
##請注意資料夾與範例程式的路徑,皆以前面章節為基礎,您可以按照您的需求修改位置
#vi /root/GreengrassCore/recipes/com.example.HelloWorld-1.0.0.json -
參考下列範例修改您的食譜。其中請以步驟 2 中的 S3_BUCKET 名稱置換 [YOUR BUCKET NAME]
{
"RecipeFormatVersion": "2020-01-25",
"ComponentName": "com.example.HelloWorld",
"ComponentVersion": "1.0.0",
"ComponentDescription": "My first AWS IoT Greengrass component.",
"ComponentPublisher": "Amazon",
"ComponentConfiguration": {
"DefaultConfiguration": {
"Message": "world"
}
},
"Manifests": [
{
"Platform": {
"os": "linux"
},
"Lifecycle": {
"Run": "python3 -u {artifacts:path}/hello_world.py
'{configuration:/Message}'\n"
},
"Artifacts": [
{
"URI": "s3://[YOUR BUCKET NAME]/artifacts/com.example.HelloWorld/1.0.0/hello_world.py"
}
]
}
]
}其中請以步驟 2 中的 S3_BUCKET 名稱置換 [YOUR BUCKET NAME],可參考下列的指令獲取 S3_BUCKET名稱。
$echo $S3_BUCKET
-
登入您的 OpenWrt,請參考下列的指令壓縮打包 GreengrassCore 資料夾並上傳至遠端機器。
##請注意資料夾與範例程式的路徑,皆以前面章節為基礎,您可以按照您的需求修改位置
#cd /root/
##您可以按照您的需求決定壓縮包的名稱,或使用您習慣的壓縮工具
#tar zcvf GreengrassCore.tgz ./GreengrassCore
##您可以按照您的需求,使用您習慣的檔案上傳工具,在此範例中我們使用scp,其中user為遠端機器的使用者名稱,remote_machine_ip為遠端機器的ip位址,/home/user/為遠端機器的指定目錄
#scp ./Greengrass.tgz user@remote_machine_ip:/home/user/ -
登入您遠端的機器,請參考下列指令解壓縮您剛剛上傳的 GreengrassCore 檔案,並透過 AWS CLI 上傳您元件的 artifacts 至Amazon S3 儲存貯體。
##請注意資料夾與範例程式的路徑,皆以前面章節為基礎,您可以按照您的需求修改位置
$cd /home/user/
$tar zxvf GreengrassCore.tgz
$aws s3 cp --recursive /home/user/GreengrassCore/ s3://$S3_BUCKET/
-
請參考下列的命令發佈您的 AWS IoT Greengrass Version 2 元件。
##請注意資料夾與範例程式的路徑,皆以前面章節為基礎,您可以按照您的需求修改位置
$cd /home/user/GreengrassCore/recipes
$aws greengrassv2 create-component-version --inline-recipe
fileb://com.example.HelloWorld-1.0.0.json您應該會得到與下列相似的返回值。其中 arn 會根據您 AWS 使用者帳號不同而異。
{
"arn": "arn:aws:greengrass:eu-
west-1:xxxxxxxxxxxxxxxxx:components:com.example.HelloWorld:versions:1.0.0",
"componentName": "com.example.HelloWorld",
"componentVersion": "1.0.0",
"creationTimestamp": 1617825194.539,
"status": {
"componentState": "REQUESTED",
"message": "NONE",
"errors": {}
}
}
-
登入您的 AWS IoT Core 終端,您可以從 Greengrass 中的 Components 看到您已發佈的元件。

參考資料
https://docs.aws.amazon.com/greengrass/v2/developerguide/getting-started.htmlhttps://catalog.us-east-1.prod.workshops.aws/v2/workshops/5ecc2416-f956-4273-b729-d0d30556013f/en-US/