R-Car/Boards/Yocto-Gen3/AWS IoT Greengrass/v5.5.0

From eLinux.org
< R-Car‎ | Boards/Yocto-Gen3‎ | AWS IoT Greengrass
Revision as of 22:51, 20 December 2021 by O futaki (talk | contribs) (ビルド手順)
Jump to: navigation, search

Introduction

This page describes how to setup the Yocto environment to use the AWS GreenGrass with R-Car and run it.

Environment

Host PC

OS Ubuntu 20.04 LTS (64bit)
Memory 8 GB or more
Storage At least 100 GB free

Boards confirmed to work

Board SoC Confirmed
R-Car Starter Kit Premier(H3) v2.0 OK
CCPF + R-Car Starter Kit Premier(H3) v2.0 OK
R-Car Starter Kit Pro(M3) v1.0 OK
R-Car Starter Kit Pro(M3) v3.0 OK
CCPF + R-Car Starter Kit Pro(M3) v1.0 OK
CCPF + R-Car Starter Kit Pro(M3) v3.0 OK

Building the BSP

  1. Install the required packages
    $ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib \
    build-essential chrpath socat cpio python3 python3-pip python3-pexpect \
    xz-utils debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa \
    libsdl1.2-dev pylint3 xterm docker.io
    
    18px <translate> Note:</translate>If the OS version of the host PC is earlier than "Ubuntu 20.04", the default gcc version is old, so use "gcc-9/g++-9" or later version.
  2. Setup Git
    $ git config --global user.email "you@example.com"
    $ git config --global user.name "Your Name"
    
  3. Build script(build.sh)
    #!/bin/bash
    
    BOARD_LIST=("h3ulcb" "m3ulcb" "h3ulcb-ccpf-sk" "m3ulcb-ccpf-sk")
    TARGET_BOARD=$1
    WORK=`pwd`/${TARGET_BOARD}
    
    # Commit ID
    POKY_COMMIT=6ebb33bdaccaeadff0c85aab27acf35723df00d8
    META_OE_COMMIT=c38d2a74f762a792046f3d3c377827b08aade513
    META_RENESAS_COMMIT=0fe77668f5d9a31a5d10449988c3d8fb8dc475c5
    META_RENESAS_CCPF_COMMIT=b49b57d6e68d5cda70aefbed34e06903484c573b
    META_VIRTUALIZATION_COMMIT=92cd3467502bd27b98a76862ca6525ce425a8479
    META_JAVA_COMMIT=62d6c0653ad69e14c21db2d4482e578400116a1b
    META_AWS_COMMIT=09a9e8845e1c0685d279a5fec12dc2764e67675c
    META_DOCKER_COMMIT=1ca1b5caf6f373dcc49db82dce50f4d8ab9f25cd
    
    Usage () {
        echo "Usage: $0 \${TARGET_BOARD_NAME}"
        echo "BOARD_NAME list: "
        for i in ${BOARD_LIST[@]}; do echo "  - $i"; done
        exit
    }
    
    # Check Param.
    if ! `IFS=$'\n'; echo "${BOARD_LIST[*]}" | grep -qx "${TARGET_BOARD}"`; then
        Usage
    fi
    
    mkdir -p ${WORK}
    cd ${WORK}
    
    # Clone basic Yocto layers in parallel
    git clone git://git.yoctoproject.org/poky &
    git clone git://git.openembedded.org/meta-openembedded &
    git clone git://github.com/renesas-rcar/meta-renesas &
    git clone git://git.yoctoproject.org/meta-virtualization &
    git clone git://git.yoctoproject.org/meta-java &
    git clone git://github.com/aws/meta-aws &
    git clone git://github.com/tkomagata/meta-docker &
    if [ "${TARGET_BOARD}" = "h3ulcb-ccpf-sk" ] || [ "${TARGET_BOARD}" = "m3ulcb-ccpf-sk" ]; then
        git clone git://github.com/renesas-rcar/meta-renesas-ccpf &
    fi
    
    # Wait for all clone operations
    wait
    
    # Switch to proper branches/commits
    cd ${WORK}/poky
    git checkout -b tmp ${POKY_COMMIT}
    cd ${WORK}/meta-openembedded
    git checkout -b tmp ${META_OE_COMMIT}
    cd ${WORK}/meta-renesas
    git checkout -b tmp ${META_RENESAS_COMMIT}
    cd ${WORK}/meta-virtualization
    git checkout -b tmp ${META_VIRTUALIZATION_COMMIT}
    cd ${WORK}/meta-java
    git checkout -b tmp ${META_JAVA_COMMIT}
    cd ${WORK}/meta-aws
    git checkout -b tmp ${META_AWS_COMMIT}
    cd ${WORK}/meta-docker
    git checkout -b tmp ${META_DOCKER_COMMIT}
    if [ "${TARGET_BOARD}" = "h3ulcb-ccpf-sk" ] || [ "${TARGET_BOARD}" = "m3ulcb-ccpf-sk" ]; then
        cd ${WORK}/meta-renesas-ccpf
        git checkout -b tmp ${META_RENESAS_CCPF_COMMIT}
    fi
    
    if [ "${TARGET_BOARD}" = "h3ulcb-ccpf-sk" ] || [ "${TARGET_BOARD}" = "m3ulcb-ccpf-sk" ]; then
        TEMPLATECONF=${WORK}/meta-renesas-ccpf/meta-rcar-gen3/docs/sample/conf/${TARGET_BOARD}/bsp/
    fi
    
    cd ${WORK}
    source poky/oe-init-build-env ${WORK}/build
    
    if [ "${TARGET_BOARD}" = "h3ulcb" ] || [ "${TARGET_BOARD}" = "m3ulcb" ]; then
        cp ${WORK}/meta-renesas/meta-rcar-gen3/docs/sample/conf/${TARGET_BOARD}/poky-gcc/bsp/bblayers.conf ${WORK}/build/conf/
        cp ${WORK}/meta-renesas/meta-rcar-gen3/docs/sample/conf/${TARGET_BOARD}/poky-gcc/bsp/local.conf ${WORK}/build/conf/
    fi
    
  4. Using build script
    $ chmod a+x build.sh
    $ ./build.sh <target_board_name>
    
    Since "target_board_name" needs to be changed depending on the board you are using, it should be set as follows.
    R-car-sk-target-board-name.png
  5. Append the following to layer configuration(build/conf/bblayers.conf)
      ${TOPDIR}/../meta-openembedded/meta-networking \
      ${TOPDIR}/../meta-openembedded/meta-filesystems \
      ${TOPDIR}/../meta-virtualization \
      ${TOPDIR}/../meta-docker/meta-rcar-gen3 \
      ${TOPDIR}/../meta-java \
      ${TOPDIR}/../meta-aws \
    
  6. Append the following to local configuration(build/conf/local.conf)
    # Docker presumes systemd
    DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
    VIRTUAL-RUNTIME_initscripts = "systemd-compat-units"
    
    # add docker to the image
    DISTRO_FEATURES_append = " virtualization docker"
    IMAGE_INSTALL_append = "  docker"
    CORE_IMAGE_EXTRA_INSTALL_append = " kernel-modules"
    
    # Add Greengrass and required packages to the image
    IMAGE_INSTALL_append = " greengrass-bin texinfo sudo openjdk-8"
    EXTRA_IMAGE_FEATURES_append = " ssh-server-openssh"
    
    # Possible provider: cacao-initial-native and jamvm-initial-native
    PREFERRED_PROVIDER_virtual/java-initial-native = "cacao-initial-native"
    
    # Possible provider: cacao-native and jamvm-native
    PREFERRED_PROVIDER_virtual/java-native = "jamvm-native"
    
    # Optional since there is only one provider for now
    PREFERRED_PROVIDER_virtual/javac-native = "ecj-bootstrap-native"
    
    IMAGE_INSTALL_append = " python3-pip"
    
  7. Build
    $ cd <target_board_name>
    $ source poky/oe-init-build-env
    $ bitbake core-image-minimal
    
    Building image can take up to a few hours depending on your host system performance.
    After the build has been completed successfully, you should see the output similar to:
    NOTE: Tasks Summary: Attempted 5383 tasks of which 5 didn't need to be rerun and all succeeded.
    
  8. build products
    Bitbake has generated all the necessary files in the following directories:
     <target_board_name>/build/tmp/deploy/images/<target_board_name>/
  9. Write image to SD card
    Refer to Loading kernel and rootfs via eMMC/SD card.
    18px <translate> Note:</translate>The above example is for "weston", and should be replaced with "minimal".

ターゲットボード Greengrass Core の起動確認

  1. R-Car SK の起動
    R-Car SK に uSD カードを挿入して、LANケーブルを接続する。
    USB デバッグシリアルケーブルを PC と接続して、AC 電源を投入する。
    PC 側では、ターミナルソフトを起動して、シリアル接続を行う。
    電源 ON は POWER SW(SW8) を押下する。
  2. SD ブートを U-Boot で設定
    SDブートの設定方法は、Configure U-Boot to boot from SD cardを参照。
  3. Greengrass Core の起動確認
    Greengrass Core が Active となっていることを確認する。
    $ systemctl status greengrass.service --no-pager
    
    Aws-status.png

AWS IoT Greengrass の設定/動作確認

以降の章では、以下のようなルールでタイトルにタグを記載する。

  • ターゲットボード(R-Car SK)での作業は、<端末>と記載する。
  • AWS クラウドの作業は、<Web>と記載する。
  • ビルドPCでの作業は、<ビルドPC>と記載する。
  1. <Web> AWSアカウントを作成
    https://console.aws.amazon.com/console/home
    AWS のアカウントを作成して、AWS マネジメントコンソールにルートユーザでログインする。
  2. <Web> IAM ユーザの作成
    下記を参考に作業用のIAM ユーザを作成する。
    https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_users_create.html#id_users_create_console
    作成時に以下のポリシーをアタッチしておくこと。
    • AWSLambda_FullAccess
    • IAMFullAccess
    • AWSIoTFullAccess
    • AWSGreengrassFullAccess
    • IAMAccessAnalyzerFullAccess
    18px <translate> Note:</translate>ユーザアクセス時に表示される、「アクセスキーID」、「シークレットアクセスキー」、「パスワード」を必ずメモすること。なお、シークレットアクセスキーとパスワードは、このタイミングでしか確認できないため、注意すること。
    Warning Warning: これら3点は、セキュリティ上、非常に重要な情報であるため、管理に十分注意すること。
    AWS のルートユーザをサインアウトして、作成した IAM ユーザでログインする。
    https://console.aws.amazon.com/console/home
  3. <Web> リージョンの設定
    画面右上から任意のリージョンを設定する。
    本手順では、「アジアパシフィック (東京) ap-northeast-1」を設定する。
  4. <Web><端末> IoT Core デバイスの作成
    事前に「ターゲットボード Greengrass Core の起動確認」を行い、端末はLANケーブルを接続してインターネットに接続できることを確認しておくこと。
    1. <Web> AWS のサービスから「IoT Core」を選択する。
      Aws-iot-core.png
    2. <Web> 左側面の領域から「Greengrass」→「使用を開始する」を選択する。
    3. <Web> 「1つの Core デバイスをセットアップ」を押下する。
    4. <Web><端末> 画面の指示に従い以下の作業を実施する。
      1. <Web> 「ステップ 1: Greengrass コアデバイスを登録する」
        任意の名称を入力する。
        本手順では、コアデバイス名を "R-CarH3SKDevice" とする。
      2. <Web> 「ステップ 2: モノのグループに追加して継続的なデプロイを適用する」
        「新しいグループ名を入力」をチェックして、任意の名称を入力する。
        本手順では、モノのグループ名を "R-CarH3SKDeviceGroup"とする。
      3. <端末> 「ステップ 3: Greengrass コアソフトウェアをインストール」
        1. 「ステップ 3.1: Java をデバイスにインストールする」
          R-Car SK のビルドで生成したイメージに含まれているため、作業不要。
        2. 「ステップ 3.2: デバイスで AWS 認証情報を設定する」
          以下のコマンドを実行し、 AWS へアクセスする情報を環境変数として設定する。
          $ export AWS_DEFAULT_REGION=ap-northeast-1
          $ export AWS_ACCESS_KEY_ID=<アクセスキーID>
          $ export AWS_SECRET_ACCESS_KEY=<シークレットアクセスキー>
          
        3. 「ステップ 3.3: インストーラを実行する」
          「インストーラのダウンロード」は作業不要。
          「インストーラの実行」は、Web ブラウザに表示されているものでは、Path が合わないため、端末にて、以下のコマンドを実行する。
          $ java -Droot="/greengrass/v2" -Dlog.store=FILE -jar /greengrass/v2/alts/init/distro/lib/Greengrass.jar \
          --aws-region ap-northeast-1 --thing-name R-CarH3SKDevice --thing-group-name R-CarH3SKDeviceGroup \
          --component-default-user ggc_user:ggc_group --provision true --setup-system-service true \
          --deploy-dev-tools true
          
          「R-CarH3SKDevice」と「R-CarH3SKDeviceGroup」部分は「ステップ 1」と「ステップ 2」で設定した値に置き替えること。
          上記コマンドを実行すると、R-Car SK 端末が AWS IoT と通信して Greengrass コアデバイスとして登録される。
          コマンドが終了して、しばらくすると Greengrass CLI が端末へデプロイされるため、以下のコマンドが実行できるか確認する。
          $ /greengrass/v2/bin/greengrass-cli -V
          
          18px <translate> Note:</translate>デプロイの状況は、以下のログで確認できる。
          $ tail -f /greengrass/v2/logs/greengrass.log
          
  5. <Web> IoT Core に送信するポリシーを追加
    端末で動作する Lambda 関数が AWS クラウドの IoT Core に対して メッセージを Publish するためにポリシーを追加する。
    1. AWS のサービスから「IAM」を選択する。
    2. サイドメニューから「ポリシー」を選択する。
    3. 「ポリシーを作成」を選択する。
    4. サービスに「IoT」を選択、アクションに「Publish」を選択、リソースに「すべてのリソース」を選択する。
      Aws-iot-core-policy.png
    5. 「次のステップ:タグ」、「次のステップ:確認」を押下していき、ポリシーの確認で任意の「名前」を入力し、「ポリシーの作成」ボタンを押下する。
      本手順では、名前を「R-CarH3SKDevice-IoT-Publish」とする。
    6. IAM の画面に戻るので、サイドメニューから「ロール」を選択する。
    7. 検索に「GreengrassV2TokenExchangeRole」を入力して、同名のロールを選択する。
    8. 「ポリシーをアタッチします」を押下して、先ほど作成したポリシーを検索して「ポリシーのアタッチ」を押下する。
  6. <端末> Lambda 関数の実行環境準備
    端末でサンプルプログラムを動作させるための環境構築を行う。
    以下のコマンドを実行する。
    $ mkdir -p /home/ggc_user
    $ chown ggc_user:ggc_group /home/ggc_user
    $ pip3 install numpy
    
  7. <Web><ビルドPC> Lambda 関数の作成
    端末へデプロイする Lambda 関数を作成する。
    1. <ビルドPC> 以下のコマンドを実行して、Lambda 関数のひな形を作成する。
      $ mkdir -p ~/lambda && touch ~/lambda/lambda_function.py
      
    2. <ビルドPC> 作成した lambda_function.py に以下のコードをコピペする。
      import datetime
      import json
      import numpy
      import boto3
      
      class DummyTemperatureSensor(object):
          def __init__(self, loc=25, scale=1, size=1):
              self.loc = loc
              self.scale = scale
              self.size = size
      
          def get_value(self):
              return numpy.random.normal(self.loc, self.scale, self.size)[0]
      
      
      def lambda_handler(event, context):
          print(event)
      
          # AWS IoT connection
          iot = boto3.client('iot-data', endpoint_url='https://xxxxxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com')
      
          # get temperature
          sensor = DummyTemperatureSensor()
      
          # set publish paramater
          topic='topic/sensor/temperature'
          payload = {
              "timestamp": str( datetime.datetime.now() ), 
              "temperature": sensor.get_value()
          }
          print(payload)
      
          # publish to AWS IoT
          iot.publish(
                  topic=topic,
                  qos=0,
                  payload=json.dumps(payload, ensure_ascii=False)
              )
      
      18px <translate> Note:</translate>上記コードの以下の部分は、自身のエンドポイントに置き替える必要がある。
            https://xxxxxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com
      エンドポイントは、以下から確認できる。
      1. <Web> AWS のサービスから「IoT Core」を選択する。
      2. <Web> サイドメニューから「設定」を選択する。
      3. <Web> デバイスデータエンドポイントの「エンドポイント」を参照する。
    3. <ビルドPC> パッケージの zip 化
      作成した lambda_function.py と boto3 パッケージを zip 圧縮する。
      $ cd ~/lambda
      $ sudo docker run --rm -v $(pwd):/var/task amazon/aws-sam-cli-build-image-python3.8:latest \
        pip install boto3 -t ./
      $ zip -r lambda_artifact.zip ./
      
      圧縮した zip ファイルは、クラウドへアップロードするため、AWS クラウドへアクセスしているPCにコピーする。
  8. <Web> Lambda 関数の登録
    作成した Lambda 関数を AWS クラウドへ登録する。
    1. AWS のサービスから「Lambda」を選択する。
    2. サイドメニューから「関数」を選択する。
    3. 「関数の作成」を選択する。
      Aws-lambda-function-create-1.png
    4. 「一から作成」にチェックを付ける。
    5. 「関数名」に任意の名称を付ける。本手順では「DummyTemperatureSensor」とする。
    6. 「ランタイム」に Python3.8 を選択する。
    7. 「アーキテクチャ」に arm64 を選択する。
    8. それ以外は、デフォルト値で「関数の作成」を押下する。
    9. 画面が切り替わったら「コードソース」の右側から、「アップロード元」→「.zip ファイル」を選択し、作成した zip ファイルをアップロード→保存する。
    10. 右上の「アクション」→「新しいバーションを発行」を選択し、発行を押下する。
  9. <Web> Lambda 関数のデプロイ
    登録した Lambda 関数を端末へデプロイする。
    1. AWS のサービスから「IoT Core」を選択する。
    2. サイドメニューから「Greengrass」→「コンポーネント」を選択する。
    3. 「コンポーネントを作成」を押下する。
      Aws-lambda-function-deploy-1.png
    4. 「Lambda 関数をインポートする」にチェックを入れる。
    5. 「Lambda 関数」に作成した、関数を選択する。
      Aws-lambda-function-deploy-2.png
    6. イベントソースの「トピック」に「topic/sensor/get」を入力する。
    7. イベントソースの「タイプ」に「AWS IoT Core MQTT」を選択する。
      Aws-lambda-function-deploy-3.png
    8. コンテナパラメータの「メモリサイズ」を「64」MB とする。
      Aws-lambda-function-deploy-4.png
    9. それ以外は、デフォルト値のまま「コンポーネントを作成」を押下する。
    10. 画面が切り替わったら、右上の「デプロイ」を押下する。
    11. デプロイ先に作成したグループを選択して「次へ」を押下する。
    12. あとは、デフォルト値のまま「次へ」を押下していき、最後の確認画面でデプロイを押下する。
  10. <WEB> <端末> 動作確認
    端末側に作成した関数がデプロイされることを確認する。
    また、端末側のログを確認して、AWS IoT → 端末へメッセージが受信できているかを確認する。
    1. <端末> R-Car SK の動作確認
      1. Lambda 関数がデプロイされているか確認する。
        以下のコマンドを実行して確認する。
        $ /greengrass/v2/bin/greengrass-cli component list
        
        実行すると以下のようなログが出力され、デプロイした関数(DummyTemperatureSensor)が、リストに表示されたことが確認できる。
        root@m3ulcb:~# /greengrass/v2/bin/greengrass-cli component list
            :
            :
        
        Component Name: DummyTemperatureSensor
            Version: 1.0.0
            State: RUNNING
            Configuration: {"containerMode":"GreengrassContainer","containerParams":{"devices":{},"memorySize":64000.0,"mountROSysfs":false,"volumes":{}},"inputPayloadEncodingType":"json","lambdaExecutionParameters":{"EnvironmentVariables":{}},"maxIdleTimeInSeconds":60.0,"maxInstancesCount":100.0,"maxQueueSize":1000.0,"pinned":true,"pubsubTopics":{"0":{"topic":"topic/sensor/get","type":"IOT_CORE"}},"statusTimeoutInSeconds":60.0,"timeoutInSeconds":3.0}
        
      2. ログを確認する。
        以下のコマンドを実行してログを確認する。
        $ cd /greengrass/v2/logs/
        $ tail -f <作成した関数名>.log
        
        以下のようなログが出力されていることを確認する。
        serviceName=<作成した関数名>, currentState=RUNNING
        
    2. <Web><端末> AWS クラウドの動作確認
      1. <Web> AWS のサービスから「IoT Core」を選択する。
      2. <Web> サイドメニューから「テスト」→「MQTT テストクライアント」を選択する。
      3. <Web> 「トピックをサブスクライブする」で「topic/sensor/temperature」を入力して「サブスクライブ」を押下する。
      4. <Web> 「トピックに公開する」で「topic/sensor/get」を入力して「発行」を押下する。
        18px <translate> Note:</translate>デフォルトのメッセージペイロードだと、端末側で文字化けするため、必要に応じて任意の英数字の文章へ変更すること。
      5. <端末> 以下のようにログにメッセージ受信内容が表示される。
        root@m3ulcb:/greengrass/v2/logs# tail -f DummyTemperatureSensor.log
        2021-12-06T04:50:40.524Z [INFO] (pool-2-thread-38) DummyTemperatureSensor: lambda_function.py:17,{'message': 'AWS IoT ??????????????????????????????'}. {serviceInstance=0, serviceName=DummyTemperatureSensor, currentState=RUNNING}
        2021-12-06T04:50:41.172Z [INFO] (pool-2-thread-38) DummyTemperatureSensor: lambda_function.py:31,{'timestamp': '2021-12-06 04:50:41.168002', 'temperature': 27.381898093845034}. {serviceInstance=0, serviceName=DummyTemperatureSensor, currentState=RUNNING}
        2021-12-06T04:51:14.939Z [INFO] (pool-2-thread-38) DummyTemperatureSensor: lambda_function.py:17,{'message': 'hello world'}. {serviceInstance=0, serviceName=DummyTemperatureSensor, currentState=RUNNING}
        2021-12-06T04:51:14.969Z [INFO] (pool-2-thread-38) DummyTemperatureSensor: lambda_function.py:31,{'timestamp': '2021-12-06 04:51:14.964931', 'temperature': 25.003559249938885}. {serviceInstance=0, serviceName=DummyTemperatureSensor, currentState=RUNNING
        
      6. <Web> サブスクリプションにメッセージが受信される。
        Aws-result1.png