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 23:18, 20 December 2021 by O futaki (talk | contribs) (ターゲットボード Greengrass Core の起動確認)
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".

Confirmation of Greengrass Core activation

  1. Startup R-Car SK
    Insert the uSD card into the R-Car SK and connect the LAN cable.
    Connect the USB debug serial cable to the PC, and turn on the AC power.
    The PC will start the terminal software and make a serial connection.
    To turn on the power, press down the POWER SW (SW8).
    If the CCPF is attached, press the POWER SW (SW4) on the CCPF board.
  2. Configure U-Boot to boot from SD card
    Refer to Configure U-Boot to boot from SD card.
  3. Confirmation of Greengrass Core activation
    Make sure that Greengrass Core is 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