ステップ 2: 更新を延期するコンポーネントを開発する - AWS IoT Greengrass

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

ステップ 2: 更新を延期するコンポーネントを開発する

このセクションでは、コアデバイスのバッテリレベルが、コンポーネントをデプロイしたときに設定したしきい値を下回ったときに、コンポーネントの更新を延期する Hello World コンポーネントを Python で開発します。このコンポーネントでは、AWS IoT Device SDK v2 for Python のプロセス間通信 (IPC) インターフェイスを使用します。SubscribeToComponentUpdates IPC オペレーションを使用して、コアデバイスがデプロイを受信したときに通知を受け取ります。次に、DeferComponentUpdateIPC オペレーションを使用して、デバイスのバッテリーレベルに基づいて更新を延期または承認します。

更新を延期する Hello World コンポーネントを開発するには
  1. 開発コンピュータ上に、コンポーネントのソースコード用のフォルダを作成します。

    mkdir com.example.BatteryAwareHelloWorld cd com.example.BatteryAwareHelloWorld
  2. テキストエディタを使用して gdk-config.json という名前のファイルを作成します。GDK CLI は gdk-config.json という名の GDK CLI 設定ファイルから読み込むことで、コンポーネントをビルドおよびパブリッシュします。この設定ファイルは、コンポーネントフォルダのルートにあります。

    例えば、Linux ベースのシステムでは、次のコマンドを実行し、GNU nano を使用してファイルを作成できます。

    nano gdk-config.json

    次の JSON をファイルにコピーします。

    • Amazon を自分の名前に置き換えます。

    • us-west-2 をコアデバイスが動作している場所である AWS リージョン に置き換えます。GDK CLI がこのコンポーネントをこの AWS リージョン にパブリッシュします。

    • を使用する S3 バケットプレフィックスgreengrass-component-artifactsに置き換えます。GDK CLI を使用してコンポーネントを公開すると、GDK CLI はコンポーネントの成果物を、この値、AWS リージョン および自分の AWS アカウント ID から形成される名前を持つ S3 バケットに、次のフォーマットを使用してアップロードします: bucketPrefix-region-accountId

      例えば、greengrass-component-artifacts および us-west-2 を指定し、AWS アカウント ID が 123456789012 の場合、GDK CLI は greengrass-component-artifacts-us-west-2-123456789012 という名前の S3 バケットを使用します。

    { "component": { "com.example.BatteryAwareHelloWorld": { "author": "Amazon", "version": "NEXT_PATCH", "build": { "build_system" : "zip" }, "publish": { "region": "us-west-2", "bucket": "greengrass-component-artifacts" } } }, "gdk_version": "1.0.0" }

    設定ファイルは、以下を指定します。

    • GDK CLI が Greengrass コンポーネントを AWS IoT Greengrass クラウドサービスにパブリッシュする際に使用するバージョン。NEXT_PATCH は、AWS IoT Greengrass クラウドサービスで利用可能な最新バージョンの次のパッチバージョンを選択するように指定します。コンポーネントに AWS IoT Greengrass クラウドサービスのバージョンがまだない場合は、GDK CLIは 1.0.0 を使用します。

    • コンポーネントのビルドシステム。zip ビルドシステムを使用した場合、GDK CLI はコンポーネントのソースを ZIP ファイルにパッケージ化して、コンポーネントの単一のアーティファクトにします。

    • GDK CLI が Greengrass コンポーネントをパブリッシュする場所となる AWS リージョン。

    • GDK CLI がコンポーネントのアーティファクトをアップロードする場所となる S3 バケットのプレフィックス。

  3. テキストエディタを使用して、main.py という名前のファイルにコンポーネントのソースコードを作成します。

    例えば、Linux ベースのシステムでは、次のコマンドを実行し、GNU nano を使用してファイルを作成できます。

    nano main.py

    ファイルに次の Python コードをコピーします。

    import json import os import sys import time import traceback from pathlib import Path from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2 HELLO_WORLD_PRINT_INTERVAL = 15 # Seconds DEFER_COMPONENT_UPDATE_INTERVAL = 30 * 1000 # Milliseconds class BatteryAwareHelloWorldPrinter(): def __init__(self, ipc_client: GreengrassCoreIPCClientV2, battery_file_path: Path, battery_threshold: float): self.battery_file_path = battery_file_path self.battery_threshold = battery_threshold self.ipc_client = ipc_client self.subscription_operation = None def on_component_update_event(self, event): try: if event.pre_update_event is not None: if self.is_battery_below_threshold(): self.defer_update(event.pre_update_event.deployment_id) print('Deferred update for deployment %s' % event.pre_update_event.deployment_id) else: self.acknowledge_update( event.pre_update_event.deployment_id) print('Acknowledged update for deployment %s' % event.pre_update_event.deployment_id) elif event.post_update_event is not None: print('Applied update for deployment') except: traceback.print_exc() def subscribe_to_component_updates(self): if self.subscription_operation == None: # SubscribeToComponentUpdates returns a tuple with the response and the operation. _, self.subscription_operation = self.ipc_client.subscribe_to_component_updates( on_stream_event=self.on_component_update_event) def close_subscription(self): if self.subscription_operation is not None: self.subscription_operation.close() self.subscription_operation = None def defer_update(self, deployment_id): self.ipc_client.defer_component_update( deployment_id=deployment_id, recheck_after_ms=DEFER_COMPONENT_UPDATE_INTERVAL) def acknowledge_update(self, deployment_id): # Specify recheck_after_ms=0 to acknowledge a component update. self.ipc_client.defer_component_update( deployment_id=deployment_id, recheck_after_ms=0) def is_battery_below_threshold(self): return self.get_battery_level() < self.battery_threshold def get_battery_level(self): # Read the battery level from the virtual battery level file. with self.battery_file_path.open('r') as f: data = json.load(f) return float(data['battery_level']) def print_message(self): message = 'Hello, World!' if self.is_battery_below_threshold(): message += ' Battery level (%d) is below threshold (%d), so the component will defer updates' % ( self.get_battery_level(), self.battery_threshold) else: message += ' Battery level (%d) is above threshold (%d), so the component will acknowledge updates' % ( self.get_battery_level(), self.battery_threshold) print(message) def main(): # Read the battery threshold and virtual battery file path from command-line args. args = sys.argv[1:] battery_threshold = float(args[0]) battery_file_path = Path(args[1]) print('Reading battery level from %s and deferring updates when below %d' % ( str(battery_file_path), battery_threshold)) try: # Create an IPC client and a Hello World printer that defers component updates. ipc_client = GreengrassCoreIPCClientV2() hello_world_printer = BatteryAwareHelloWorldPrinter( ipc_client, battery_file_path, battery_threshold) hello_world_printer.subscribe_to_component_updates() try: # Keep the main thread alive, or the process will exit. while True: hello_world_printer.print_message() time.sleep(HELLO_WORLD_PRINT_INTERVAL) except InterruptedError: print('Subscription interrupted') hello_world_printer.close_subscription() except Exception: print('Exception occurred', file=sys.stderr) traceback.print_exc() exit(1) if __name__ == '__main__': main()

    この Python アプリケーションは次を実行します。

    • 後でコアデバイスで作成する仮想バッテリレベルファイルから、コアデバイスのバッテリレベルを読み取ります。この仮想バッテリーレベルファイルは実際のバッテリーを模倣しているため、バッテリーのないコアデバイスでもこのチュートリアルを完了できます。

    • バッテリのしきい値と、仮想バッテリレベルファイルへのパスに対するコマンドライン引数を読み取ります。コンポーネント recipe は、設定パラメータに基づいてこれらのコマンドライン引数を設定するため、コンポーネントをデプロイするときにこれらの値はカスタマイズできます。

    • AWS IoT Device SDK v2 for Python で IPC クライアント V2 を使用して、AWS IoT Greengrass Core ソフトウェアと通信します。オリジナルの IPC クライアントと比較して、IPC クライアント V2で は、カスタムコンポーネントで IPC を使用するために記述する必要があるコードの量が減っています。

    • SubscribeToComponentUpdates IPC オペレーションを使用して更新通知をサブスクライブします。AWS IoT Greengrass Core ソフトウェアは、各デプロイの前後に通知を送信します。コンポーネントは、通知を受信するたびに次の関数を呼び出します。通知が今後のデプロイに関するものである場合、コンポーネントはバッテリ残量がしきい値より低いかどうかを確認します。バッテリー残量がしきい値を下回っている場合、コンポーネントは DeferComponentUpdate IPC オペレーションを使用して更新を 30 秒間延期します。それ以外の、バッテリ残量がしきい値を下回っていない場合には、コンポーネントは更新を承認し、更新が続行されます。

      def on_component_update_event(self, event): try: if event.pre_update_event is not None: if self.is_battery_below_threshold(): self.defer_update(event.pre_update_event.deployment_id) print('Deferred update for deployment %s' % event.pre_update_event.deployment_id) else: self.acknowledge_update( event.pre_update_event.deployment_id) print('Acknowledged update for deployment %s' % event.pre_update_event.deployment_id) elif event.post_update_event is not None: print('Applied update for deployment') except: traceback.print_exc()
      注記

      AWS IoT Greengrass Core ソフトウェアは、ローカルデプロイに関する更新通知は送信しないため、このコンポーネントは AWS IoT Greengrass クラウドサービスを使ってデプロイしてテストします。

  4. テキストエディタを使用して、 recipe.json または recipe.yaml という名前のファイルにコンポーネント recipe を作成します。コンポーネント recipe は、コンポーネントのメタデータ、デフォルト設定パラメータ、プラットフォームに固有のライフサイクルスクリプトを定義します。

    JSON

    例えば、Linux ベースのシステムでは、次のコマンドを実行し、GNU nano を使用してファイルを作成できます。

    nano recipe.json

    次の JSON をファイルにコピーします。

    { "RecipeFormatVersion": "2020-01-25", "ComponentName": "COMPONENT_NAME", "ComponentVersion": "COMPONENT_VERSION", "ComponentDescription": "This Hello World component defers updates when the battery level is below a threshold.", "ComponentPublisher": "COMPONENT_AUTHOR", "ComponentConfiguration": { "DefaultConfiguration": { "BatteryThreshold": 50, "LinuxBatteryFilePath": "/home/ggc_user/virtual_battery.json", "WindowsBatteryFilePath": "C:\\Users\\ggc_user\\virtual_battery.json" } }, "Manifests": [ { "Platform": { "os": "linux" }, "Lifecycle": { "install": "python3 -m pip install --user awsiotsdk --upgrade", "run": "python3 -u {artifacts:decompressedPath}/com.example.BatteryAwareHelloWorld/main.py \"{configuration:/BatteryThreshold}\" \"{configuration:/LinuxBatteryFilePath}\"" }, "Artifacts": [ { "Uri": "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/com.example.BatteryAwareHelloWorld.zip", "Unarchive": "ZIP" } ] }, { "Platform": { "os": "windows" }, "Lifecycle": { "install": "py -3 -m pip install --user awsiotsdk --upgrade", "run": "py -3 -u {artifacts:decompressedPath}/com.example.BatteryAwareHelloWorld/main.py \"{configuration:/BatteryThreshold}\" \"{configuration:/WindowsBatteryFilePath}\"" }, "Artifacts": [ { "Uri": "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/com.example.BatteryAwareHelloWorld.zip", "Unarchive": "ZIP" } ] } ] }
    YAML

    例えば、Linux ベースのシステムでは、次のコマンドを実行し、GNU nano を使用してファイルを作成できます。

    nano recipe.yaml

    ファイルに次の YAML をコピーします。

    --- RecipeFormatVersion: "2020-01-25" ComponentName: "COMPONENT_NAME" ComponentVersion: "COMPONENT_VERSION" ComponentDescription: "This Hello World component defers updates when the battery level is below a threshold." ComponentPublisher: "COMPONENT_AUTHOR" ComponentConfiguration: DefaultConfiguration: BatteryThreshold: 50 LinuxBatteryFilePath: "/home/ggc_user/virtual_battery.json" WindowsBatteryFilePath: "C:\\Users\\ggc_user\\virtual_battery.json" Manifests: - Platform: os: linux Lifecycle: install: python3 -m pip install --user awsiotsdk --upgrade run: python3 -u {artifacts:decompressedPath}/com.example.BatteryAwareHelloWorld/main.py "{configuration:/BatteryThreshold}" "{configuration:/LinuxBatteryFilePath}" Artifacts: - Uri: "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/com.example.BatteryAwareHelloWorld.zip" Unarchive: ZIP - Platform: os: windows Lifecycle: install: py -3 -m pip install --user awsiotsdk --upgrade run: py -3 -u {artifacts:decompressedPath}/com.example.BatteryAwareHelloWorld/main.py "{configuration:/BatteryThreshold}" "{configuration:/WindowsBatteryFilePath}" Artifacts: - Uri: "s3://BUCKET_NAME/COMPONENT_NAME/COMPONENT_VERSION/com.example.BatteryAwareHelloWorld.zip" Unarchive: ZIP

    この recipe は以下を指定します。

    • バッテリのしきい値、Linux コアデバイスの仮想バッテリファイルパス、および Windows コアデバイスの仮想バッテリファイルパスに対するデフォルト設定パラメータ。

    • AWS IoT Device SDK v2 for Python の最新バージョンをインストールする install ライフサイクル。

    • main.py で Python アプリケーションを実行する run ライフサイクル。

    • COMPONENT_NAME および COMPONENT_VERSION などのプレースホルダ。GDK CLI がコンポーネント recipe を構築するときにこの情報を置き換えます。

    コンポーネント recipe の詳細については、「AWS IoT Greengrass コンポーネントレシピリファレンス」を参照してください。