

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

# V2 で V1 アプリケーションをテストする新しいデバイスをセットアップ
<a name="set-up-test-device"></a>

本番環境のデバイスへのリスクを最小限に抑えるには、本番環境のデバイスをアップグレードする前に、新しいデバイスを作成して V2 で VV1 アプリケーションをテストします。

前のステップで選択したランタイムに基づいて、次のいずれかの設定ガイドを選択します。
+ **オプション A - Greengrass nucleus ランタイム**: Greengrass nucleus [V2 で V1 アプリケーションをテストする新しいデバイスをセットアップ](set-up-v2-test-device.md)を選択した場合はフォローします。このオプションを使用すると、コードの変更を最小限に抑えながら Lambda 関数を Lambda コンポーネントとしてインポートし、ローカルシャドウサービス、クライアントデバイス、コネクタなどの V1 機能をサポートできます。
+ **オプション B - Greengrass nucleus lite ランタイム**: Greengrass nucleus lite [V2 (Greengrass nucleus lite) で V1 アプリケーションをテストする新しいデバイスを設定する](set-up-v2-test-device-lite.md)を選択した場合はフォローします。このオプションでは、 AWS IoT Device SDK V2 またはコンポーネント SDK を使用して Lambda 関数を汎用 AWS IoT Greengrass コンポーネントに変換する必要がありますが、リソースに制約のあるデバイス用に最適化されています。

# V2 で V1 アプリケーションをテストする新しいデバイスをセットアップ
<a name="set-up-v2-test-device"></a>

新しい AWS IoT Greengrass V2 コアデバイスをセットアップして、 AWS IoT Greengrass V1 アプリケーション用に AWS提供されたコンポーネントと AWS Lambda 機能をデプロイしてテストします。この V2 コアデバイスを使用して、コアデバイスでネイティブプロセスを実行する追加のカスタム Greengrass コンポーネントを開発およびテストすることもできます。V2 コアデバイスでアプリケーションをテストした後、既存の V1 コアデバイスを V2 にアップグレードし、V1 機能を提供する V2 コンポーネントをデプロイできます。



## ステップ 1: を新しいデバイスにインストール AWS IoT Greengrass V2 する
<a name="install-v2-test-device"></a>

Core AWS IoT Greengrass ソフトウェア v2.x を新しいデバイスにインストールします。[[getting started tutorial]](getting-started.md) (入門チュートリアル) に従ってデバイスをセットアップし、コンポーネントを開発およびデプロイする方法を学ぶことができます。このチュートリアルでは、[[automatic provisioning]](quick-installation.md) (自動プロビジョニング) を使用して、デバイスをすばやくセットアップできます。 AWS IoT Greengrass Core ソフトウェア v2.x をインストールするときは、[Greengrass CLI ](greengrass-cli-component.md)をデプロイする引`--deploy-dev-tools`数を指定して、デバイス上でコンポーネントを直接開発、テスト、デバッグできるようにします。プロキシの背後で AWS IoT Greengrass Core ソフトウェアをインストールする方法やハードウェアセキュリティモジュール (HSM) を使用する方法など、その他のインストールオプションの詳細については、「」を参照してください[AWS IoT Greengrass Core ソフトウェアをインストールします。](install-greengrass-core-v2.md)。

### (オプション) Amazon CloudWatch Logs へのログ記録を有効にする
<a name="enable-cloudwatch-logging-v2"></a>

V2 コアデバイスが Amazon CloudWatch Logs にログをアップロードできるようにするには、 AWSが提供する[ログマネージャーコンポーネント](log-manager-component.md)をデプロイします。CloudWatch Logs を使用してコンポーネントログを表示できるため、コアデバイスのファイルシステムにアクセスせずにデバッグとトラブルシューティングを行うことができます。詳細については、「[AWS IoT Greengrass ログのモニタリング](monitor-logs.md)」を参照してください。

## ステップ 2: AWS IoT Greengrass V1 アプリケーションを移行する AWS IoT Greengrass V2 コンポーネントを作成してデプロイする
<a name="run-v1-applications"></a>

ほとんどの AWS IoT Greengrass V1 アプリケーションは で実行できます AWS IoT Greengrass V2。Lambda 関数は、 で実行されるコンポーネントとしてインポートでき AWS IoT Greengrass V2、 AWS IoT Greengrass コネクタと同じ機能を提供する [AWSが提供するコンポーネント](public-components.md)を使用できます。

カスタムコンポーネントを開発して、Greengrass コアデバイスで実行する任意の機能またはランタイムをビルドすることもできます。コンポーネントをローカルで開発およびテストする方法の詳細については、「[AWS IoT Greengrass コンポーネントを作成する](create-components.md)」を参照してください。

**Topics**
+ [V1 Lambda 関数をインポートする](#run-v1-lambda-functions)
+ [V1 コネクタを使用する](#use-v1-connectors)
+ [Docker コンテナを実行する](#run-v1-docker-containers)
+ [V1 Greengrass デバイスを接続する](#connect-v1-greengrass-devices)
+ [ローカルシャドウサービスを有効にする](#enable-shadow-service)
+ [との統合 AWS IoT SiteWise](#integrate-with-iot-sitewise)

### V1 Lambda 関数をインポートする
<a name="run-v1-lambda-functions"></a>

Lambda 関数を AWS IoT Greengrass V2 コンポーネントとしてインポートできます。以下のアプローチのいずれかを選択できます。
+ V1 Lambda 関数を Greengrass コンポーネントとして直接インポートします。
+ Lambda 関数を更新して v2 AWS IoT Device SDK の Greengrass ライブラリを使用し、Lambda 関数を Greengrass コンポーネントとしてインポートします。
+ Lambda 以外のコードと AWS IoT Device SDK v2 を使用して、Lambda 関数と同じ機能を実装するカスタムコンポーネントを作成します。

Lambda 関数がストリームマネージャーやローカルシークレットなどの機能を使用する場合は、これらの機能をパッケージ化する AWSが提供するコンポーネントへの依存関係を定義する必要があります。Lambda 関数コンポーネントをデプロイすると、依存関係として定義する各機能のコンポーネントもデプロイに含まれます。デプロイでは、コアデバイスにデプロイするシークレットなどのパラメータを設定できます。V1 のすべての機能で、V2 の Lambda 関数にコンポーネントの依存関係が必要なわけではありません。次のリストは、V2 Lambda 関数コンポーネントで V1 機能を使用する方法を示しています。 V2 
+ **他の AWS サービスにアクセスする**

  Lambda 関数が AWS 認証情報を使用して他の AWS サービスにリクエストを行う場合、コアデバイスのトークン交換ロールは、Lambda 関数が使用する AWS オペレーションの実行をコアデバイスに許可する必要があります。詳細については、「[コアデバイスが AWS サービスとやり取りできるように認可する](device-service-role.md)」を参照してください。
+ **ストリームマネージャー**

  Lambda 関数がストリームマネージャーを使用している場合は、関数をインポートするときのコンポーネントの依存関係として `aws.greengrass.StreamManager` を指定します。ストリームマネージャーコンポーネントをデプロイするときに、ターゲットコアデバイスに設定するストリームマネージャーパラメータを指定します。コアデバイスのトークン交換ロールは、コアデバイスがストリームマネージャーで使用する AWS クラウド 送信先にアクセスすることを許可する必要があります。詳細については、「[ストリームマネージャー](stream-manager-component.md)」を参照してください。
+ **ローカルシークレット**

  Lambda 関数がローカルシークレットを使用している場合は、関数をインポートするときのコンポーネントの依存関係として `aws.greengrass.SecretManager` を指定します。シークレットマネージャーコンポーネントをデプロイするときは、ターゲットコアデバイスにデプロイするシークレットリソースを指定します。コアデバイスのトークン交換ロールは、コアデバイスがデプロイするシークレットリソースを取得できるようにする必要があります。詳細については、「[シークレットマネージャー](secret-manager-component.md)」を参照してください。

  Lambda 関数コンポーネントをデプロイするときは、 AWS IoT Device SDK V2 で [GetSecretValue ](ipc-secret-manager.md) [IPC オペレーションを使用するアクセス許可を付与する IPC 認可ポリシー](interprocess-communication.md#ipc-authorization-policies)を持つように設定します。
+ **ローカルシャドウ**

  Lambda 関数がローカルシャドウとやり取りする場合は、 AWS IoT Device SDK V2 を使用するように Lambda 関数コードを更新する必要があります。また、関数をインポートするときのコンポーネントの依存関係として `aws.greengrass.ShadowManager` を指定する必要があります。詳細については、「[デバイスシャドウとやり取り](interact-with-shadows.md)」を参照してください。

  Lambda 関数コンポーネントをデプロイするときは、 AWS IoT Device SDK V2 でシャ[ドウ](ipc-local-shadows.md) [IPC オペレーションを使用するアクセス許可を付与する IPC 認可ポリシー](interprocess-communication.md#ipc-authorization-policies)を持つように設定します。
+ **サブスクリプション**
  + Lambda 関数がクラウドソースからのメッセージをサブスクライブする場合は、関数をインポートするときにそれらのサブスクリプションをイベントソースとして指定します。
  + Lambda 関数が別の Lambda 関数からのメッセージをサブスクライブする場合、または Lambda 関数が AWS IoT Core 他の Lambda 関数にメッセージを発行する場合は、Lambda 関数をデプロイするときに[レガシーサブスクリプションルーターコンポーネント](legacy-subscription-router-component.md)を設定してデプロイします。レガシーサブスクリプションルーターコンポーネントをデプロイするときは、Lambda 関数が使用するサブスクリプションを指定します。
**注記**  <a name="legacy-subscription-router-requirement-note"></a>
レガシーサブスクリプションルーターコンポーネントは、Lambda 関数が AWS IoT Greengrass Core SDK で `publish()`関数を使用する場合にのみ必要です。 AWS IoT Device SDK V2 でプロセス間通信 (IPC) インターフェイスを使用するように Lambda 関数コードを更新する場合、レガシーサブスクリプションルーターコンポーネントをデプロイする必要はありません。詳細については、次の[プロセス間通信](interprocess-communication.md)サービスを参照してください。  
[ローカルメッセージをパブリッシュ/サブスクライブする](ipc-publish-subscribe.md)
[AWS IoT Core MQTT メッセージを発行/サブスクライブする](ipc-iot-core-mqtt.md)
  + Lambda 関数がローカルに接続されたデバイスからのメッセージをサブスクライブする場合は、関数をインポートするときにそれらのサブスクリプションをイベントソースとして指定します。また、接続されたデバイスからイベントソースとして指定したローカルのパブリッシュ/サブスクライブトピックにメッセージを中継するために、[MQTT ブリッジコンポーネント](mqtt-bridge-component.md)を設定およびデプロイする必要があります。
  + Lambda 関数がローカル接続デバイスにメッセージを発行する場合は、 AWS IoT Device SDK V2 を使用して[ローカル発行/サブスクライブメッセージを発行](ipc-publish-subscribe.md)するように Lambda 関数コードを更新する必要があります。また、ローカルのパブリッシュ/サブスクライブメッセージブローカーから接続されたデバイスにメッセージを中継するために、[[MQTT bridge component]](mqtt-bridge-component.md) (MQTT ブリッジコンポーネント) を設定およびデプロイする必要があります。
+ **ローカルボリュームとデバイス**

  コンテナ化された Lambda 関数がローカルボリュームまたはデバイスにアクセスする場合は、Lambda 関数をインポートするときにそれらのボリュームとデバイスを指定します。この機能では、コンポーネントの依存関係は必要ありません。

詳細については、「[AWS Lambda 関数を実行する](run-lambda-functions.md)」を参照してください。

### V1 コネクタを使用する
<a name="use-v1-connectors"></a>

一部の AWS IoT Greengrass コネクタと同じ機能を提供する AWSが提供するコンポーネントをデプロイできます。デプロイを作成するときに、コネクタのパラメータを設定できます。

以下の AWS IoT Greengrass V2 コンポーネントは Greengrass V1 コネクタ機能を提供します。
+ [CloudWatch メトリクスのコンポーネント](cloudwatch-metrics-component.md)
+ [AWS IoT Device Defender コンポーネント](device-defender-component.md)
+ [Firehose コンポーネント](kinesis-firehose-component.md)
+ [Modbus-RTU プロトコルアダプタコンポーネント](modbus-rtu-protocol-adapter-component.md)
+ [Amazon SNS コンポーネント](sns-component.md)

### Docker コンテナを実行する
<a name="run-v1-docker-containers"></a>

AWS IoT Greengrass V2 は、V1 Docker アプリケーションデプロイコネクタを直接置き換えるコンポーネントを提供しません。ただし、Docker アプリケーションマネージャーコンポーネントを使用して Docker イメージをダウンロードし、ダウンロードしたイメージから Docker コンテナを実行するカスタムコンポーネントを作成できます。詳細については、「[Docker コンテナの実行](run-docker-container.md)」および「[Docker アプリケーションマネージャー](docker-application-manager-component.md)」を参照してください。

### V1 Greengrass デバイスを接続する
<a name="connect-v1-greengrass-devices"></a>

の接続されたデバイスは AWS IoT Greengrass V1 、 のクライアントデバイスと呼ばれます AWS IoT Greengrass V2。クライアントデバイスの AWS IoT Greengrass V2 サポートは と下位互換性があるため AWS IoT Greengrass V1、アプリケーションコードを変更せずに V1 クライアントデバイスを V2 コアデバイスに接続できます。クライアントデバイスが V2 コアデバイスに接続できるようにするには、クライアントデバイスのサポートを有効にする Greengrass コンポーネントをデプロイし、クライアントデバイスをコアデバイスに関連付けます。クライアントデバイス、 AWS IoT Core クラウドサービス、Greengrass コンポーネント (Lambda 関数を含む) 間でメッセージを中継するには、[[MQTT bridge component]](mqtt-bridge-component.md) (MQTT ブリッジコンポーネント) をデプロイおよび設定します。[[IP detector component]](ip-detector-component.md) (IP 検出コンポーネント) をデプロイして接続情報を自動検出することも、エンドポイントを手動で管理することも可能です。詳細については、「[ローカル IoT デバイスとやり取りする](interact-with-local-iot-devices.md)」を参照してください。

### ローカルシャドウサービスを有効にする
<a name="enable-shadow-service"></a>

では AWS IoT Greengrass V2、ローカルシャドウサービスは、 AWSが提供するシャドウマネージャーコンポーネントによって実装されます。 には、名前付きシャドウのサポート AWS IoT Greengrass V2 も含まれています。コンポーネントがローカルシャドウとやり取りし、シャドウの状態を に同期できるようにするには AWS IoT Core、シャドウマネージャーコンポーネントを設定してデプロイし、コンポーネントコードでシャドウ IPC オペレーションを使用します。詳細については、「[デバイスシャドウとやり取り](interact-with-shadows.md)」を参照してください。

### との統合 AWS IoT SiteWise
<a name="integrate-with-iot-sitewise"></a>

V1 コアデバイスを AWS IoT SiteWise ゲートウェイとして使用する場合は、[手順に従って](https://docs.aws.amazon.com/iot-sitewise/latest/userguide/configure-gateway-ggv2.html)新しい V2 コアデバイスを AWS IoT SiteWise ゲートウェイとしてセットアップします。 AWS IoT SiteWise には、 AWS IoT SiteWise コンポーネントをデプロイするインストールスクリプトが用意されています。

## ステップ 3: AWS IoT Greengrass V2 アプリケーションをテストする
<a name="test-v2-features"></a>

V2 コンポーネントを作成して新しい V2 コアデバイスにデプロイしたら、アプリケーションが期待を満たしていることを確認します。デバイスのログをチェックして、コンポーネントの標準出力 (stdout) および標準エラー (stderr) メッセージを表示できます。詳細については、「[AWS IoT Greengrass ログのモニタリング](monitor-logs.md)」を参照してください。

[Greengrass CLI](greengrass-cli-component.md) をコアデバイスにデプロイした場合は、それを使用してコンポーネントとその設定をデバッグできます。詳細については、「[Greengrass CLI コマンド](gg-cli-reference.md)」を参照してください。

アプリケーションが V2 コアデバイスで動作することを確認したら、アプリケーションの Greengrass コンポーネントを他のコアデバイスにデプロイできます。ネイティブプロセスまたは Docker コンテナを実行するカスタムコンポーネントを開発した場合は、まず[それらのコンポーネントをサービスに公開](publish-components.md)して、他のコアデバイスにデプロイする必要があります。 AWS IoT Greengrass 

# V2 (Greengrass nucleus lite) で V1 アプリケーションをテストする新しいデバイスを設定する
<a name="set-up-v2-test-device-lite"></a>

Greengrass nucleus lite を使用して新しいデバイスをセットアップし、 AWS IoT Greengrass V1 アプリケーションを V2 に移行するために作成する汎用コンポーネントをテストします。Greengrass nucleus lite は、リソースに制約のあるデバイス用に最適化された軽量ランタイムです。このデバイスを使用して、ネイティブプロセスを実行するカスタム Greengrass コンポーネントを開発およびテストできます。Greengrass nucleus lite デバイスでアプリケーションをテストしたら、Greengrass nucleus lite を実行している他のデバイスに V2 コンポーネントをデプロイするか、既存の V1 コアデバイスを V2 にアップグレードできます。



## ステップ 1: 新しいデバイスに Greengrass nucleus lite をインストールする
<a name="lite-step-1-install"></a>

Greengrass nucleus lite を新しいデバイスにインストールします。[Greengrass nucleus lite のインストールガイド](https://docs.aws.amazon.com/greengrass/v2/developerguide/greengrass-nucleus-lite-component.html#greengrass-nucleus-lite-component-install)に従ってデバイスをセットアップします。

**注記**  
Greengrass nucleus lite は現在、ローカルシャドウサービス、クライアントデバイス、またはコネクタをサポートしていません。このガイドに進む前に、V1 アプリケーションがこれらの機能に依存していないことを確認してください。

## ステップ 2: AWS IoT Greengrass V1 Lambda 関数を移行するための汎用コンポーネントを作成してデプロイする
<a name="lite-step-2-convert-lambda"></a>

Greengrass nucleus lite で AWS IoT Greengrass V1 Lambda 関数の機能をレプリケートするには、汎用コンポーネントに変換する必要があります。これには、 AWS IoT Greengrass Core SDK の代わりに AWS IoT Device SDK V2 または AWS IoT Greengrass コンポーネント SDK を使用するように Lambda 関数コードを書き換えることが含まれます。

次の表に、このガイドの V2 コンポーネントの例で使用される SDKs を示します。


| SDK | 最小バージョン | 
| --- | --- | 
| [AWS IoT Device SDK for Python v2](https://github.com/aws/aws-iot-device-sdk-python-v2) | v1.11.3 | 
| [AWS IoT Device SDK for Java v2](https://github.com/aws/aws-iot-device-sdk-java-v2) | v1.9.3 | 
| [AWS IoT Device SDK for JavaScript v2](https://github.com/aws/aws-iot-device-sdk-js-v2) | v1.12.0 | 
| [AWS IoT Greengrass コンポーネント SDK (C/C\$1\$1)](https://github.com/aws-greengrass/aws-greengrass-component-sdk) (現在プレビュー中) | v0.4.0 | 

以下の例は、 AWS IoT Greengrass V1 Core SDK と同等の汎用コンポーネントを使用する Lambda 関数を示しています。2 つの主なシナリオでは、コンポーネントコード、レシピ、ビルド手順が複数のプログラミング言語で記述されています。
+ **ローカル通信** - ローカル pub/sub を使用して同じデバイス上の他のコンポーネントと通信するコンポーネント
+ **クラウド通信** - AWS IoT Core または他の AWS サービスと通信するコンポーネント

### シナリオ 1: ローカル通信 (パブリッシャー → プロセッサ → サブスクライバー)
<a name="lite-example-local-communication"></a>

このシナリオでは、ローカル pub/sub 通信を使用する V1 Lambda 関数を V2 汎用コンポーネントに変換する方法を示します。

#### アプリケーションのアーキテクチャ
<a name="lite-example-1-scenario"></a>

この例では、次の 3 つのコンポーネントを使用します。
+ パブリッシャー Lambda が温度データを公開する
+ プロセッサ Lambda がデータを受信して処理する
+ プロセッサ Lambda が処理結果をサブスクライバー Lambda に発行する

以下のコード例は、ローカル通信のメッセージのサブスクライブと発行の両方を示すプロセッサ Lambda に焦点を当てています。

##### V1 グループのサブスクリプション
<a name="lite-example-1-v1-subscriptions"></a>

では AWS IoT Greengrass V1、次のグループサブスクリプションにより、Lambda 関数間の通信が有効になります。

サブスクリプション 1: パブリッシャー → プロセッサ
+ ソース: Lambda (パブリッシャー)
+ ターゲット: Lambda (プロセッサ)
+ トピック: センサー/温度

サブスクリプション 2: プロセッサ → サブスクライバー
+ ソース: Lambda (プロセッサ)
+ ターゲット: Lambda (サブスクライバー)
+ トピック: Lambda/アラート

#### Processor Lambda 関数 (V1)
<a name="lite-example-1-v1-code"></a>

------
#### [ Python ]

```
import greengrasssdk
import json

iot_client = greengrasssdk.client('iot-data')

def lambda_handler(event, context):
    """
    Receives temperature from publisher Lambda,
    processes it, and forwards to subscriber Lambda
    """
    # Receive from publisher Lambda.
    sensor_id = event['sensor_id']
    temperature = event['temperature']
    
    print(f"Received from sensor {sensor_id}: {temperature}°F")
    
    # Process: Check if temperature is high.
    if temperature > 80:
        alert_data = {
            'sensor_id': sensor_id,
            'temperature': temperature,
            'alert': 'HIGH_TEMPERATURE'
        }
        
        # Publish to another Lambda using greengrasssdk.
        iot_client.publish(
            topic='lambda/alerts',
            payload=json.dumps(alert_data)
        )
        
        print(f"Alert sent to subscriber Lambda")
    
    return {'statusCode': 200}
```

------
#### [ Java ]

```
import com.amazonaws.greengrass.javasdk.IotDataClient;
import com.amazonaws.greengrass.javasdk.model.PublishRequest;
import com.amazonaws.services.lambda.runtime.Context;
import com.google.gson.Gson;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class TemperatureProcessorLambda {
    private static final Gson gson = new Gson();
    private final IotDataClient iotDataClient;

    public TemperatureProcessorLambda() {
        this.iotDataClient = new IotDataClient();
    }

    public String handleRequest(Map<String, Object> event, Context context) {
        /*
         * Receives temperature from publisher Lambda,
         * processes it, and forwards to subscriber Lambda
         */

        // Receive from publisher Lambda.
        String sensorId = (String) event.get("sensor_id");
        Number temp = (Number) event.get("temperature");
        int temperature = temp.intValue();

        System.out.println("Received from sensor " + sensorId + ": " + temperature + "°F");

        // Process: Check if temperature is high.
        if (temperature > 80) {
            Map<String, Object> alertData = new HashMap<>();
            alertData.put("sensor_id", sensorId);
            alertData.put("temperature", temperature);
            alertData.put("alert", "HIGH_TEMPERATURE");

            // Publish to another Lambda using greengrasssdk.
            String payload = gson.toJson(alertData);
            PublishRequest publishRequest = new PublishRequest()
                .withTopic("lambda/alerts")
                .withPayload(ByteBuffer.wrap(payload.getBytes(StandardCharsets.UTF_8)));

            iotDataClient.publish(publishRequest);

            System.out.println("Alert sent to subscriber Lambda");
        }

        return "Success";
    }
}
```

------
#### [ JavaScript ]

```
const greengrasssdk = require('aws-greengrass-core-sdk');

const iotClient = new greengrasssdk.IotData();

/**
 * Greengrass v1 Lambda function
 * Receives temperature from publisher Lambda,
 * processes it, and forwards to subscriber Lambda
 */
exports.handler = function(event, context) {
    // Receive from publisher Lambda.
    const sensorId = event.sensor_id;
    const temperature = event.temperature;
    
    console.log(`Received from sensor ${sensorId}: ${temperature}°F`);
    
    // Process: Check if temperature is high.
    if (temperature > 80) {
        const alertData = {
            sensor_id: sensorId,
            temperature: temperature,
            alert: 'HIGH_TEMPERATURE'
        };
        
        // Publish to another Lambda using greengrasssdk.
        const params = {
            topic: 'lambda/alerts',
            payload: JSON.stringify(alertData)
        };
        
        iotClient.publish(params, (err) => {
            if (err) {
                console.error('Error publishing alert:', err);
                context.fail(err);
            } else {
                console.log('Alert sent to subscriber Lambda');
                context.succeed('Success');
            }
        });
    } else {
        context.succeed('Success');
    }
};
```

------
#### [ C ]

```
#include <aws/greengrass/greengrasssdk.h>
#include <stdio.h>
#include <string.h>
#include <jansson.h>  // For JSON parsing.

static aws_greengrass_iot_data_client *iot_client = NULL;

void on_message_received(const char *topic, const uint8_t *payload, size_t payload_len, void *user_data) {
    // Parse the incoming message.
    char *payload_str = strndup((char *)payload, payload_len);
    json_error_t error;
    json_t *event = json_loads(payload_str, 0, &error);
    free(payload_str);
    
    if (!event) {
        fprintf(stderr, "Error parsing JSON: %s\n", error.text);
        return;
    }
    
    // Receive from publisher Lambda.
    json_t *sensor_id_obj = json_object_get(event, "sensor_id");
    json_t *temperature_obj = json_object_get(event, "temperature");
    
    const char *sensor_id = json_string_value(sensor_id_obj);
    int temperature = json_integer_value(temperature_obj);
    
    printf("Received from sensor %s: %d°F\n", sensor_id, temperature);
    
    // Process: Check if temperature is high.
    if (temperature > 80) {
        // Create alert data.
        json_t *alert_data = json_object();
        json_object_set_new(alert_data, "sensor_id", json_string(sensor_id));
        json_object_set_new(alert_data, "temperature", json_integer(temperature));
        json_object_set_new(alert_data, "alert", json_string("HIGH_TEMPERATURE"));
        
        // Convert to JSON string.
        char *alert_payload = json_dumps(alert_data, JSON_COMPACT);
        
        // Publish to another Lambda using greengrasssdk.
        aws_greengrass_publish_params params = {
            .topic = "lambda/alerts",
            .payload = (uint8_t *)alert_payload,
            .payload_len = strlen(alert_payload)
        };
        
        aws_greengrass_iot_data_publish(iot_client, &params);
        
        printf("Alert sent to subscriber Lambda\n");
        
        free(alert_payload);
        json_decref(alert_data);
    }
    
    json_decref(event);
}

int main(int argc, char *argv[]) {
    // Initialize Greengrass SDK.
    iot_client = aws_greengrass_iot_data_client_new();
    
    // Subscribe to temperature sensor topic.
    aws_greengrass_subscribe_params subscribe_params = {
        .topic = "sensors/temperature",
        .callback = on_message_received,
        .user_data = NULL
    };
    
    aws_greengrass_iot_data_subscribe(iot_client, &subscribe_params);
    
    printf("Temperature Processor Lambda started\n");
    printf("Subscribed to sensors/temperature\n");
    printf("Waiting for sensor data...\n");
    
    // Keep the Lambda running.
    while (1) {
        sleep(1);
    }
    
    return 0;
}
```

------
#### [ C\$1\$1 ]

```
#include <aws/greengrass/greengrasssdk.h>
#include <iostream>
#include <string>
#include <memory>
#include <jansson.h> // For JSON parsing.
#include <unistd.h>

class TemperatureProcessor {
private:
    std::unique_ptr<aws_greengrass_iot_data_client, 
                    decltype(&aws_greengrass_iot_data_client_destroy)> iot_client;
    
    static void message_callback_wrapper(const char *topic, 
                                        const uint8_t *payload, 
                                        size_t payload_len, 
                                        void *user_data) {
        auto* processor = static_cast<TemperatureProcessor*>(user_data);
        processor->on_message_received(topic, payload, payload_len);
    }

public:
    TemperatureProcessor() 
        : iot_client(aws_greengrass_iot_data_client_new(), 
                     aws_greengrass_iot_data_client_destroy) {
        if (!iot_client) {
            throw std::runtime_error("Failed to create Greengrass IoT client");
        }
    }

    void on_message_received(const char *topic, 
                            const uint8_t *payload, 
                            size_t payload_len) {
        // Parse the incoming message.
        std::string payload_str(reinterpret_cast<const char*>(payload), payload_len);
        
        json_error_t error;
        json_t *event = json_loads(payload_str.c_str(), 0, &error);
        
        if (!event) {
            std::cerr << "Error parsing JSON: " << error.text << std::endl;
            return;
        }

        json_t *sensor_id_obj = json_object_get(event, "sensor_id");
        json_t *temperature_obj = json_object_get(event, "temperature");
        
        const char *sensor_id = json_string_value(sensor_id_obj);
        int temperature = json_integer_value(temperature_obj);
        
        std::cout << "Received from sensor " << sensor_id 
                  << ": " << temperature << "°F" << std::endl;

        if (temperature > 80) {
            send_alert(sensor_id, temperature);
        }

        json_decref(event);
    }

    void send_alert(const char *sensor_id, int temperature) {
        // Create alert data.
        json_t *alert_data = json_object();
        json_object_set_new(alert_data, "sensor_id", json_string(sensor_id));
        json_object_set_new(alert_data, "temperature", json_integer(temperature));
        json_object_set_new(alert_data, "alert", json_string("HIGH_TEMPERATURE"));

        // Convert to JSON string.
        char *alert_payload = json_dumps(alert_data, JSON_COMPACT);

        // Publish to another Lambda using greengrasssdk.
        aws_greengrass_publish_params params = {
            .topic = "lambda/alerts",
            .payload = reinterpret_cast<uint8_t*>(alert_payload),
            .payload_len = strlen(alert_payload)
        };
        
        aws_greengrass_iot_data_publish(iot_client.get(), &params);
        
        std::cout << "Alert sent to subscriber Lambda" << std::endl;

        free(alert_payload);
        json_decref(alert_data);
    }

    void subscribe_to_topic(const std::string& topic) {
        aws_greengrass_subscribe_params subscribe_params = {
            .topic = topic.c_str(),
            .callback = message_callback_wrapper,
            .user_data = this
        };
        
        aws_greengrass_iot_data_subscribe(iot_client.get(), &subscribe_params);
        
        std::cout << "Temperature Processor Lambda started" << std::endl;
        std::cout << "Subscribed to " << topic << std::endl;
        std::cout << "Waiting for sensor data..." << std::endl;
    }

    void run() {
        // Keep the Lambda running.
        while (true) {
            sleep(1);
        }
    }
};

int main(int argc, char *argv[]) {
    try {
        TemperatureProcessor processor;
        processor.subscribe_to_topic("sensors/temperature");
        processor.run();
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}
```

------

#### 汎用コンポーネント (V2)
<a name="lite-example-1-v2-code"></a>

で同じ機能を実現するには AWS IoT Greengrass V2、以下を使用して汎用コンポーネントを作成します。

##### 1. コンポーネントコード
<a name="lite-example-1-component-code"></a>

------
#### [ Python ]

前提条件: このコンポーネントコードを使用する前に、Greengrass デバイスに AWS IoT Device SDK for Python をインストールして検証します。

```
# Install the SDK
pip3 install awsiotsdk

# Verify installation
python3 -c "import awsiot.greengrasscoreipc.clientv2; print('SDK installed successfully')"
```

インストール中に依存関係の競合が発生した場合は、 の特定のバージョンをインストールしてみてください AWS IoT Device SDK。

検証コマンドで「SDK が正常にインストールされました」と表示される場合は、コンポーネントコードを使用する準備が整います。

```
from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2
from awsiot.greengrasscoreipc.model import (
    PublishMessage,
    JsonMessage
)
import time

ipc_client = GreengrassCoreIPCClientV2()

def on_sensor_data(event):
    """
    Receives temperature from sensor publisher component,
    processes it, and forwards to alert component
    """
    try:
        # Receive from publisher component.
        data = event.json_message.message
        sensor_id = data['sensor_id']
        temperature = data['temperature']
        
        print(f"Received from sensor {sensor_id}: {temperature}°F")
        
        # Process: Check if temperature is high.
        if temperature > 80:
            alert_data = {
                'sensor_id': sensor_id,
                'temperature': temperature,
                'alert': 'HIGH_TEMPERATURE'
            }
            
            # Publish to another component (AlertHandler).
            ipc_client.publish_to_topic(
                topic='component/alerts',
                publish_message=PublishMessage(
                    json_message=JsonMessage(message=alert_data)
                )
            )
            
            print(f"Alert sent to AlertHandler component")
    
    except Exception as e:
        print(f"Error processing sensor data: {e}")

def main():
    print("Temperature Processor component starting...")
    
    # Subscribe to sensor data from publisher component.
    ipc_client.subscribe_to_topic(
        topic='sensors/temperature',
        on_stream_event=on_sensor_data
    )
    
    print("Subscribed to sensors/temperature")
    print("Waiting for sensor data...")
    
    # Keep running.
    while True:
        time.sleep(1)

if __name__ == '__main__':
    main()
```

------
#### [ Java ]

```
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClientV2;
import software.amazon.awssdk.aws.greengrass.model.PublishMessage;
import software.amazon.awssdk.aws.greengrass.model.PublishToTopicRequest;
import software.amazon.awssdk.aws.greengrass.model.JsonMessage;
import software.amazon.awssdk.aws.greengrass.model.SubscribeToTopicRequest;
import software.amazon.awssdk.aws.greengrass.model.SubscriptionResponseMessage;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class TemperatureProcessor {
    private static GreengrassCoreIPCClientV2 ipcClient;

    public static void main(String[] args) {
        System.out.println("Temperature Processor component starting...");

        try (GreengrassCoreIPCClientV2 client = GreengrassCoreIPCClientV2.builder().build()) {
            ipcClient = client;

            SubscribeToTopicRequest subscribeRequest = new SubscribeToTopicRequest()
                .withTopic("sensors/temperature");

            ipcClient.subscribeToTopic(
                subscribeRequest, 
                TemperatureProcessor::onSensorData,
                Optional.empty(),
                Optional.empty()
            );

            System.out.println("Subscribed to sensors/temperature");
            System.out.println("Waiting for sensor data...");

            while (true) {
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public static void onSensorData(SubscriptionResponseMessage message) {
        try {
            Map<String, Object> data = message.getJsonMessage().getMessage();
            String sensorId = (String) data.get("sensor_id");
            Number temp = (Number) data.get("temperature");
            int temperature = temp.intValue();

            System.out.println("Received from sensor " + sensorId + ": " + temperature + "F");

            if (temperature > 80) {
                Map<String, Object> alertData = new HashMap<>();
                alertData.put("sensor_id", sensorId);
                alertData.put("temperature", temperature);
                alertData.put("alert", "HIGH_TEMPERATURE");

                JsonMessage jsonMessage = new JsonMessage().withMessage(alertData);
                PublishMessage publishMessage = new PublishMessage().withJsonMessage(jsonMessage);
                PublishToTopicRequest publishRequest = new PublishToTopicRequest()
                    .withTopic("component/alerts")
                    .withPublishMessage(publishMessage);

                ipcClient.publishToTopic(publishRequest);
                System.out.println("Alert sent to AlertHandler component");
            }
        } catch (Exception e) {
            System.err.println("Error processing sensor data: " + e.getMessage());
        }
    }
}
```

------
#### [ JavaScript ]

```
const greengrasscoreipc = require('aws-iot-device-sdk-v2').greengrasscoreipc;

class TemperatureProcessor {
    constructor() {
        this.ipcClient = null;
    }

    async start() {
        console.log('Temperature Processor component starting...');
        
        try {
            this.ipcClient = greengrasscoreipc.createClient();
            await this.ipcClient.connect();
            
            const subscribeRequest = {
                topic: 'sensors/temperature'
            };

            const streamingOperation = this.ipcClient.subscribeToTopic(subscribeRequest);
            
            streamingOperation.on('message', (message) => {
                this.onSensorData(message);
            });
            
            streamingOperation.on('streamError', (error) => {
                console.error('Stream error:', error);
            });
            
            streamingOperation.on('ended', () => {
                console.log('Subscription stream ended');
            });
            
            await streamingOperation.activate();
            
            console.log('Subscribed to sensors/temperature');
            console.log('Waiting for sensor data...');
            
        } catch (error) {
            console.error('Error starting component:', error);
            process.exit(1);
        }
    }

    async onSensorData(message) {
        try {
            const data = message.jsonMessage.message;
            
            const sensorId = data.sensor_id;
            const temperature = data.temperature;
            
            console.log(`Received from sensor ${sensorId}: ${temperature}°F`);
            
            if (temperature > 80) {
                const alertData = {
                    sensor_id: sensorId,
                    temperature: temperature,
                    alert: 'HIGH_TEMPERATURE'
                };
                
                const publishRequest = {
                    topic: 'component/alerts',
                    publishMessage: {
                        jsonMessage: {
                            message: alertData
                        }
                    }
                };
                
                await this.ipcClient.publishToTopic(publishRequest);
                console.log('Alert sent to AlertHandler component');
            }
            
        } catch (error) {
            console.error('Error processing sensor data:', error);
        }
    }
}

// Start the component.
const processor = new TemperatureProcessor();
processor.start();
```

------
#### [ C ]

```
#include <gg/buffer.h>
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/map.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define SUBSCRIBE_TOPIC "sensors/temperature"
#define PUBLISH_TOPIC "component/alerts"

typedef struct {
    char sensor_id[64];
    int64_t temperature;
} AlertData;

static pthread_mutex_t alert_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t alert_cond = PTHREAD_COND_INITIALIZER;
static AlertData pending_alert;
static bool has_pending_alert = false;

static void *alert_publisher_thread(void *arg) {
    (void) arg;
    
    while (true) {
        pthread_mutex_lock(&alert_mutex);
        while (!has_pending_alert) {
            pthread_cond_wait(&alert_cond, &alert_mutex);
        }
        
        AlertData alert = pending_alert;
        has_pending_alert = false;
        pthread_mutex_unlock(&alert_mutex);
        
        GgBuffer sensor_id_buf = { .data = (uint8_t *)alert.sensor_id, .len = strlen(alert.sensor_id) };
        GgMap payload = GG_MAP(
            gg_kv(GG_STR("sensor_id"), gg_obj_buf(sensor_id_buf)),
            gg_kv(GG_STR("temperature"), gg_obj_i64(alert.temperature)),
            gg_kv(GG_STR("alert"), gg_obj_buf(GG_STR("HIGH_TEMPERATURE")))
        );
        
        GgError ret = ggipc_publish_to_topic_json(GG_STR(PUBLISH_TOPIC), payload);
        
        if (ret != GG_ERR_OK) {
            fprintf(stderr, "Failed to publish alert\n");
        } else {
            printf("Alert sent to AlertHandler component\n");
        }
    }
    
    return NULL;
}

static void on_sensor_data(
    void *ctx, GgBuffer topic, GgObject payload, GgIpcSubscriptionHandle handle
) {
    (void) ctx;
    (void) topic;
    (void) handle;
    
    if (gg_obj_type(payload) != GG_TYPE_MAP) {
        fprintf(stderr, "Expected JSON message\n");
        return;
    }
    
    GgMap map = gg_obj_into_map(payload);
    
    GgObject *sensor_id_obj;
    if (!gg_map_get(map, GG_STR("sensor_id"), &sensor_id_obj)) {
        fprintf(stderr, "Missing sensor_id field\n");
        return;
    }
    GgBuffer sensor_id = gg_obj_into_buf(*sensor_id_obj);
    
    GgObject *temperature_obj;
    if (!gg_map_get(map, GG_STR("temperature"), &temperature_obj)) {
        fprintf(stderr, "Missing temperature field\n");
        return;
    }
    int64_t temperature = gg_obj_into_i64(*temperature_obj);
    
    printf("Received from sensor %.*s: %lld°F\n", 
           (int)sensor_id.len, sensor_id.data, (long long)temperature);
    
    if (temperature > 80) {
        pthread_mutex_lock(&alert_mutex);
        snprintf(pending_alert.sensor_id, sizeof(pending_alert.sensor_id),
                 "%.*s", (int)sensor_id.len, sensor_id.data);
        pending_alert.temperature = temperature;
        has_pending_alert = true;
        pthread_cond_signal(&alert_cond);
        pthread_mutex_unlock(&alert_mutex);
    }
}

int main(void) {
    setvbuf(stdout, NULL, _IONBF, 0);
    printf("Temperature Processor component starting...\n");
    
    gg_sdk_init();
    
    GgError ret = ggipc_connect();
    if (ret != GG_ERR_OK) {
        fprintf(stderr, "Failed to connect to Greengrass nucleus\n");
        exit(1);
    }
    printf("Connected to Greengrass IPC\n");
    
    // Start alert publisher thread.
    pthread_t alert_thread;
    if (pthread_create(&alert_thread, NULL, alert_publisher_thread, NULL) != 0) {
        fprintf(stderr, "Failed to create alert publisher thread\n");
        exit(1);
    }
    
    GgIpcSubscriptionHandle handle;
    ret = ggipc_subscribe_to_topic(
        GG_STR(SUBSCRIBE_TOPIC),
        &on_sensor_data,
        NULL,
        &handle
    );
    
    if (ret != GG_ERR_OK) {
        fprintf(stderr, "Failed to subscribe to topic\n");
        exit(1);
    }
    
    printf("Subscribed to %s\n", SUBSCRIBE_TOPIC);
    printf("Waiting for sensor data...\n");
    
    // Keep running.
    while (true) {
        sleep(1);
    }
    
    return 0;
}
```

------
#### [ C\$1\$1 ]

```
#include <gg/ipc/client.hpp>
#include <gg/buffer.hpp>
#include <gg/object.hpp>
#include <gg/types.hpp>

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <string>
#include <string_view>
#include <thread>

struct AlertData {
    std::string sensor_id;
    int64_t temperature;
};

static std::mutex alert_mutex;
static std::condition_variable alert_cv;
static AlertData pending_alert;
static bool has_pending_alert = false;

void alert_publisher_thread() {
    auto& client = gg::ipc::Client::get();
    
    while (true) {
        std::unique_lock<std::mutex> lock(alert_mutex);
        alert_cv.wait(lock, [] { return has_pending_alert; });
        
        AlertData alert = pending_alert;
        has_pending_alert = false;
        lock.unlock();
        
        // Create alert payload as JSON string.
        std::string json_payload = "{\"sensor_id\":\"" + alert.sensor_id + 
                                  "\",\"temperature\":" + std::to_string(alert.temperature) + 
                                  ",\"alert\":\"HIGH_TEMPERATURE\"}";
        
        // Convert to Buffer and publish.
        gg::Buffer buffer(json_payload);
        auto error = client.publish_to_topic("component/alerts", buffer);
        
        if (error) {
            std::cerr << "Failed to publish alert\n";
        } else {
            std::cout << "Alert sent to AlertHandler component\n";
        }
    }
}

class SensorCallback : public gg::ipc::LocalTopicCallback {
    void operator()(
        std::string_view topic,
        gg::Object payload,
        gg::ipc::Subscription& handle
    ) override {
        (void) topic;
        (void) handle;
        
        // Payload is a Buffer containing JSON string.
        if (payload.index() != GG_TYPE_BUF) {
            std::cerr << "Expected Buffer message\n";
            return;
        }
        
        // Extract buffer using gg::get.
        auto buffer = gg::get<std::span<uint8_t>>(payload);
        std::string json_str(reinterpret_cast<const char*>(buffer.data()), buffer.size());
        
        // Simple JSON parsing for demo.
        std::string sensor_id = "sensor1"; 
        int64_t temperature = 0;
        
        // Extract temperature (simple string search).
        size_t temp_pos = json_str.find("\"temperature\":");
        if (temp_pos != std::string::npos) {
            temp_pos += 14; // Skip "temperature".
            size_t end_pos = json_str.find_first_of(",}", temp_pos);
            if (end_pos != std::string::npos) {
                temperature = std::stoll(json_str.substr(temp_pos, end_pos - temp_pos));
            }
        }
        
        std::cout << "Received from sensor " << sensor_id << ": " 
                  << temperature << "°F\n";
        
        if (temperature > 80) {
            std::lock_guard<std::mutex> lock(alert_mutex);
            pending_alert = {sensor_id, temperature};
            has_pending_alert = true;
            alert_cv.notify_one();
        }
    }
};

int main() {
    // Disable stdout buffering for real-time logging.
    std::cout.setf(std::ios::unitbuf);
    
    std::cout << "Temperature Processor component starting..." << std::endl;
    
    auto& client = gg::ipc::Client::get();
    std::cout << "Got client instance" << std::endl;
    
    auto error = client.connect();
    std::cout << "Connect returned, error code: " << error.value() << std::endl;
    
    if (error) {
        std::cerr << "Failed to connect to Greengrass nucleus: " << error.message() << std::endl;
        return 1;
    }
    
    std::cout << "Connected to Greengrass IPC" << std::endl;
    
    // Start alert publisher thread.
    std::thread alert_thread(alert_publisher_thread);
    alert_thread.detach();
    
    // Handler must be static lifetime if subscription handle is not held.
    static SensorCallback handler;
    error = client.subscribe_to_topic("sensors/temperature", handler);
    
    if (error) {
        std::cerr << "Failed to subscribe to topic: " << error.message() << std::endl;
        return 1;
    }
    
    std::cout << "Subscribed to sensors/temperature" << std::endl;
    std::cout << "Waiting for sensor data..." << std::endl;
    
    // Keep running.
    while (true) {
        using namespace std::chrono_literals;
        std::this_thread::sleep_for(1s);
    }
    
    return 0;
}
```

------

##### 2. コンポーネントを構築してパッケージ化する
<a name="lite-example-1-build-component"></a>

一部の言語では、デプロイ前に構築またはパッケージ化が必要です。

------
#### [ Python ]

Python ではコンパイルは必要ありません。コンポーネントは .py ファイルを直接使用できます。

------
#### [ Java ]

すべての依存関係がバンドルされた実行可能 JAR を構築するには:

1. プロジェクトディレクトリに `pom.xml` ファイルを作成します。

   ```
   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
   
       <!-- Basic project information: organization, component name, and version -->
       <groupId>com.example</groupId>
       <artifactId>temperature-processor</artifactId>
       <version>1.0.0</version>
   
       <properties>
           <!-- Java 11 LTS (Long Term Support) is recommended for Greengrass v2 components -->
           <maven.compiler.source>11</maven.compiler.source>
           <maven.compiler.target>11</maven.compiler.target>
       </properties>
   
       <dependencies>
           <!-- AWS IoT Device SDK for Java - provides IPC client for Greengrass v2 local communication -->
           <dependency>
               <groupId>software.amazon.awssdk.iotdevicesdk</groupId>
               <artifactId>aws-iot-device-sdk</artifactId>
               <version>1.25.1</version>
           </dependency>
       </dependencies>
   
       <build>
           <plugins>
               <!-- Maven Shade Plugin - creates a standalone JAR with all dependencies included for Greengrass deployment -->
               <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-shade-plugin</artifactId>
                   <version>3.2.4</version>
                   <executions>
                       <execution>
                           <phase>package</phase>
                           <goals>
                               <goal>shade</goal>
                           </goals>
                           <configuration>
                               <transformers>
                                   <!-- Set the main class for the executable JAR -->
                                   <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                       <mainClass>TemperatureProcessor</mainClass>
                                   </transformer>
                               </transformers>
                               <filters>
                                   <!-- Exclude signature files to avoid security exceptions -->
                                   <filter>
                                       <artifact>*:*</artifact>
                                       <excludes>
                                           <exclude>META-INF/*.SF</exclude>
                                           <exclude>META-INF/*.DSA</exclude>
                                           <exclude>META-INF/*.RSA</exclude>
                                       </excludes>
                                   </filter>
                               </filters>
                           </configuration>
                       </execution>
                   </executions>
               </plugin>
           </plugins>
       </build>
   </project>
   ```

1. JAR を構築します。

   ```
   mvn clean package
   ```

   これにより、すべての依存関係を含む `target/temperature-processor-1.0.0.jar` が作成されます。

1. JAR を S3 バケットにアップロードしてデプロイします。

------
#### [ JavaScript ]

Node.js コンポーネントをすべての依存関係でパッケージ化するには:

1. `package.json` ファイルを作成します。

   ```
   {
     "name": "temperature-processor",
     "version": "1.0.0",
     "description": "Temperature processor component for Greengrass v2",
     "main": "TemperatureProcessor.js",
     "dependencies": {
       "aws-iot-device-sdk-v2": "^1.21.0"
     },
     "engines": {
       "node": ">=14.0.0"
     }
   }
   ```

1. 開発マシンに依存関係をインストールします。

   ```
   npm install
   ```

   これにより、v2 AWS AWS IoT Device SDK を含む`node_modules`フォルダが作成されます。

1. デプロイ用のパッケージ:

   ```
   zip -r TemperatureProcessor.zip TemperatureProcessor.js node_modules/ package.json
   ```

1. zip ファイルを S3 バケットにアップロードしてデプロイします。

**注記**  
Greengrass デバイスには Node.js ランタイムがインストールされている必要があります (バージョン 14 以降）。コンポーネントアーティファクト`npm install`にはバンドルされた`node_modules`フォルダ内のすべての依存関係が含まれているため、Greengrass コアデバイスで を実行する必要はありません。

------
#### [ C ]

**前提条件**:

SDK と コンポーネントを構築するには、次のビルド依存関係が必要です。
+ GCC または Clang
+ CMake (バージョン 3.22 以上)
+ または Ninja を作成する

**ビルドの依存関係をインストールします。**

Ubuntu/Debian の場合:

```
sudo apt install build-essential cmake
```

Amazon Linux で

```
sudo yum install gcc cmake make
```

**コンポーネントの CMakeLists.txt ファイルを作成します。**

```
cmake_minimum_required(VERSION 3.10)
project(TemperatureProcessor C)

set(CMAKE_C_STANDARD 11)

# Add AWS Greengrass Component SDK
add_subdirectory(aws-greengrass-component-sdk)

# Build your component executable
add_executable(temperature_processor temperature_processor.c)
target_link_libraries(temperature_processor gg-sdk)
```

**ビルドステップ:**

```
# Clone the AWS Greengrass Component SDK into your project
git clone https://github.com/aws-greengrass/aws-greengrass-component-sdk.git

# Build your component
cmake -B build -D CMAKE_BUILD_TYPE=MinSizeRel
make -C build -j$(nproc)

# The binary 'temperature_processor' is in ./build/
# Upload this binary to S3 for deployment
```

------
#### [ C\$1\$1 ]

**前提条件**:

SDK と コンポーネントを構築するには、次のビルド依存関係が必要です。
+ C\$1\$120 をサポートする GCC または Clang
+ CMake (バージョン 3.22 以上)
+ または Ninja を作成する

**ビルドの依存関係をインストールします。**

Ubuntu/Debian の場合:

```
sudo apt install build-essential cmake
```

Amazon Linux で

```
sudo yum install gcc-c++ cmake make
```

**コンポーネントの CMakeLists.txt ファイルを作成します。**

```
cmake_minimum_required(VERSION 3.10)
project(TemperatureProcessor CXX)

set(CMAKE_CXX_STANDARD 20)

# Add SDK as subdirectory
add_subdirectory(aws-greengrass-component-sdk)

# Add C++ SDK subdirectory
add_subdirectory(aws-greengrass-component-sdk/cpp)

add_executable(temperature_processor temperature_processor.cpp)
target_link_libraries(temperature_processor gg-sdk++)
```

**ビルドステップ:**

```
# Clone the AWS Greengrass Component SDK into your project
git clone https://github.com/aws-greengrass/aws-greengrass-component-sdk.git

# Build your component
cmake -B build -D CMAKE_BUILD_TYPE=MinSizeRel
make -C build -j$(nproc)

# The binary 'temperature_processor' will be in ./build/
# Upload this binary to S3 for deployment
```

------

##### 3. コンポーネントレシピ
<a name="lite-example-1-component-recipe"></a>

コンポーネントが使用する実際のトピックで「リソース」配列を更新します。

------
#### [ Python ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.TemperatureProcessor",
  "ComponentVersion": "1.0.0",
  "ComponentType": "aws.greengrass.generic",
  "ComponentDescription": "Receives sensor data and forwards alerts to AlertHandler",
  "ComponentPublisher": "[Your Company]",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.TemperatureProcessor:pubsub:1": {
            "policyDescription": "Allows access to subscribe to sensor topics",
            "operations": [
              "aws.greengrass#SubscribeToTopic"
            ],
            "resources": [
              "sensors/temperature"
            ]
          },
          "com.example.TemperatureProcessor:pubsub:2": {
            "policyDescription": "Allows access to publish to alert topics",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "component/alerts"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "python3 -u {artifacts:path}/temperature_processor.py"
      },
      "Artifacts": [
        {
          "Uri": "s3://YOUR-BUCKET/artifacts/com.example.TemperatureProcessor/1.0.0/temperature_processor.py"
        }
      ]
    }
  ]
}
```

------
#### [ Java ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.TemperatureProcessor",
  "ComponentVersion": "1.0.0",
  "ComponentType": "aws.greengrass.generic",
  "ComponentDescription": "Receives sensor data and forwards alerts to AlertHandler",
  "ComponentPublisher": "[Your Company]",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.TemperatureProcessor:pubsub:1": {
            "policyDescription": "Allows access to subscribe to sensor topics",
            "operations": [
              "aws.greengrass#SubscribeToTopic"
            ],
            "resources": [
              "sensors/temperature"
            ]
          },
          "com.example.TemperatureProcessor:pubsub:2": {
            "policyDescription": "Allows access to publish to alert topics",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "component/alerts"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "java -jar {artifacts:path}/TemperatureProcessor.jar"
      },
      "Artifacts": [
        {
          "Uri": "s3://YOUR-BUCKET/artifacts/com.example.TemperatureProcessor/1.0.0/TemperatureProcessor.jar"
        }
      ]
    }
  ]
}
```

------
#### [ JavaScript ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.TemperatureProcessor",
  "ComponentVersion": "1.0.0",
  "ComponentType": "aws.greengrass.generic",
  "ComponentDescription": "Receives sensor data and forwards alerts to AlertHandler",
  "ComponentPublisher": "[Your Company]",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.TemperatureProcessor:pubsub:1": {
            "policyDescription": "Allows access to subscribe to sensor topics",
            "operations": [
              "aws.greengrass#SubscribeToTopic"
            ],
            "resources": [
              "sensors/temperature"
            ]
          },
          "com.example.TemperatureProcessor:pubsub:2": {
            "policyDescription": "Allows access to publish to alert topics",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "component/alerts"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "cd {artifacts:decompressedPath}/TemperatureProcessor && node TemperatureProcessor.js"
      },
      "Artifacts": [
        {
          "Uri": "s3://YOUR-BUCKET/artifacts/com.example.TemperatureProcessor/1.0.0/TemperatureProcessor.zip",
          "Unarchive": "ZIP"
        }
      ]
    }
  ]
}
```

------
#### [ C/C\$1\$1 ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.TemperatureProcessor",
  "ComponentVersion": "1.0.0",
  "ComponentType": "aws.greengrass.generic",
  "ComponentDescription": "Receives sensor data and forwards alerts to AlertHandler",
  "ComponentPublisher": "[Your Company]",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.pubsub": {
          "com.example.TemperatureProcessor:pubsub:1": {
            "policyDescription": "Allows access to subscribe to sensor topics",
            "operations": [
              "aws.greengrass#SubscribeToTopic"
            ],
            "resources": [
              "sensors/temperature"
            ]
          },
          "com.example.TemperatureProcessor:pubsub:2": {
            "policyDescription": "Allows access to publish to alert topics",
            "operations": [
              "aws.greengrass#PublishToTopic"
            ],
            "resources": [
              "component/alerts"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/temperature_processor"
      },
      "Artifacts": [
        {
          "Uri": "s3://YOUR-BUCKET/artifacts/com.example.TemperatureProcessor/1.0.0/temperature_processor"
        }
      ]
    }
  ]
}
```

------

### シナリオ 2: クラウド通信
<a name="lite-example-cloud-communication"></a>

このシナリオでは、 と通信する V1 Lambda 関数 AWS IoT Core を V2 汎用コンポーネントに変換する方法を示します。

#### アプリケーションのアーキテクチャ
<a name="lite-example-2-scenario"></a>

この例では、クラウド接続アーキテクチャを使用しています。
+ AWS IoT Core がデバイスにコマンドを送信する
+ Controller Lambda がコマンドを受信して処理する
+ Controller Lambda がテレメトリデータを に送信する AWS IoT Core

この例では、 からのメッセージの受信とメッセージの発行の両方を示すコントローラー Lambda に焦点を当てています AWS IoT Core。

##### V1 グループのサブスクリプション
<a name="lite-example-2-v1-subscriptions"></a>

では AWS IoT Greengrass V1、次のグループサブスクリプションにより、Lambda 関数と 間の通信が有効になります AWS IoT Core。

サブスクリプション 1: IoT クラウド → Lambda
+ ソース: IoT クラウド
+ ターゲット: Lambda (DeviceController)
+ トピック: commands/device1

サブスクリプション 2: Lambda → IoT クラウド
+ ソース: Lambda (DeviceController)
+ ターゲット: IoT クラウド
+ トピック: テレメトリ/device1

#### コントローラー Lambda 関数 (V1)
<a name="lite-example-2-v1-code"></a>

------
#### [ Python ]

```
import greengrasssdk
import json
import time

iot_client = greengrasssdk.client('iot-data')

def lambda_handler(event, context):
    """
    Receives commands from IoT Core,
    processes them, and sends telemetry back to cloud
    """
    # Receive command from IoT Core.
    command = event.get('command')
    device_id = event.get('device_id', 'device1')

    print(f"Received command from cloud: {command}")

    # Process command.
    if command == 'get_status':
        status = get_device_status()

        # Send telemetry back to IoT Core.
        telemetry_data = {
            'device_id': device_id,
            'status': status,
            'timestamp': time.time()
        }

        iot_client.publish(
            topic=f'telemetry/{device_id}',
            payload=json.dumps(telemetry_data)
        )

        print(f"Telemetry sent to cloud: {telemetry_data}")

    return {'statusCode': 200}

def get_device_status():
    """Get current device status"""
    # Simulate getting device status.
    return 'online'
```

------
#### [ Java ]

```
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.greengrass.javasdk.IotDataClient;
import com.amazonaws.greengrass.javasdk.model.PublishRequest;
import com.google.gson.Gson;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class DeviceControllerLambda {
    private static final Gson gson = new Gson();
    private final IotDataClient iotDataClient;

    public DeviceControllerLambda() {
        this.iotDataClient = new IotDataClient();
    }

    public String handleRequest(Map<String, Object> event, Context context) {
        /*
         * Receives commands from IoT Core,
         * processes them, and sends telemetry back to cloud
         */

        // Receive command from IoT Core.
        String command = (String) event.get("command");
        String deviceId = event.containsKey("device_id") ? 
            (String) event.get("device_id") : "device1";

        System.out.println("Received command from cloud: " + command);

        // Process command.
        if ("get_status".equals(command)) {
            String status = getDeviceStatus();

            // Send telemetry back to IoT Core.
            Map<String, Object> telemetryData = new HashMap<>();
            telemetryData.put("device_id", deviceId);
            telemetryData.put("status", status);
            telemetryData.put("timestamp", System.currentTimeMillis() / 1000.0);

            String payload = gson.toJson(telemetryData);
            PublishRequest publishRequest = new PublishRequest()
                .withTopic("telemetry/" + deviceId)
                .withPayload(ByteBuffer.wrap(payload.getBytes(StandardCharsets.UTF_8)));

            iotDataClient.publish(publishRequest);

            System.out.println("Telemetry sent to cloud: " + telemetryData);
        }

        return "Success";
    }

    private String getDeviceStatus() {
        // Simulate getting device status.
        return "online";
    }
}
```

------
#### [ JavaScript ]

```
const greengrasssdk = require('aws-greengrass-core-sdk');

const iotClient = new greengrasssdk.IotData();

/**
 * Receives commands from IoT Core and sends telemetry back.
 */
exports.handler = function(event, context) {
    console.log('Received command from IoT Core:', JSON.stringify(event));
    
    const command = event.command;
    const deviceId = event.device_id || 'device1';
    
    console.log(`Processing command: ${command}`);
    
    if (command === 'get_status') {
        const status = 'online';
        
        const telemetryData = {
            device_id: deviceId,
            status: status,
            timestamp: Date.now() / 1000
        };
        
        // Publish telemetry to IoT Core using greengrasssdk.
        const params = {
            topic: `telemetry/${deviceId}`,
            payload: JSON.stringify(telemetryData)
        };
        
        iotClient.publish(params, (err) => {
            if (err) {
                console.error('Error publishing telemetry:', err);
                context.fail(err);
            } else {
                console.log('Telemetry sent to IoT Core:', JSON.stringify(telemetryData));
                context.succeed('Success');
            }
        });
    } else {
        context.succeed('Success');
    }
};
```

------
#### [ C ]

```
#include <aws/greengrass/greengrasssdk.h>
#include <stdio.h>
#include <string.h>
#include <jansson.h>
#include <time.h>

static aws_greengrass_iot_data_client *iot_client = NULL;

const char* get_device_status(void) {
    // Simulate getting device status.
    return "online";
}

void on_cloud_command(const char *topic, const uint8_t *payload, size_t payload_len, void *user_data) {
    // Parse incoming command from IoT Core.
    char *payload_str = strndup((char *)payload, payload_len);
    json_error_t error;
    json_t *event = json_loads(payload_str, 0, &error);
    free(payload_str);
    
    if (!event) {
        fprintf(stderr, "Error parsing JSON: %s\n", error.text);
        return;
    }
    
    // Extract command and device_id.
    json_t *command_obj = json_object_get(event, "command");
    json_t *device_id_obj = json_object_get(event, "device_id");
    
    const char *command = json_string_value(command_obj);
    const char *device_id = device_id_obj ? json_string_value(device_id_obj) : "device1";
    
    printf("Received command from cloud: %s\n", command);
    
    // Process command.
    if (command && strcmp(command, "get_status") == 0) {
        const char *status = get_device_status();
        
        // Send telemetry back to IoT Core.
        json_t *telemetry_data = json_object();
        json_object_set_new(telemetry_data, "device_id", json_string(device_id));
        json_object_set_new(telemetry_data, "status", json_string(status));
        json_object_set_new(telemetry_data, "timestamp", json_real(time(NULL)));
        
        char *telemetry_payload = json_dumps(telemetry_data, JSON_COMPACT);
        
        // Publish telemetry to IoT Core.
        char telemetry_topic[256];
        snprintf(telemetry_topic, sizeof(telemetry_topic), "telemetry/%s", device_id);
        
        aws_greengrass_publish_params params = {
            .topic = telemetry_topic,
            .payload = (uint8_t *)telemetry_payload,
            .payload_len = strlen(telemetry_payload)
        };
        
        aws_greengrass_iot_data_publish(iot_client, &params);
        
        printf("Telemetry sent to cloud: %s\n", telemetry_payload);
    
        free(telemetry_payload);
        json_decref(telemetry_data);
    }
    
    json_decref(event);
}

int main(int argc, char *argv[]) {
    // Initialize Greengrass SDK.
    iot_client = aws_greengrass_iot_data_client_new();
    
    // Subscribe to commands from IoT Core.
    aws_greengrass_subscribe_params subscribe_params = {
        .topic = "commands/device1",
        .callback = on_cloud_command,
        .user_data = NULL
    };
    
    aws_greengrass_iot_data_subscribe(iot_client, &subscribe_params);
    
    printf("Device Controller Lambda started\n");
    printf("Subscribed to commands/device1\n");
    printf("Waiting for commands from IoT Core...\n");
    
    // Keep the Lambda running.
    while (1) {
        sleep(1);
    }
    
    return 0;
}
```

------
#### [ C\$1\$1 ]

```
#include <aws/greengrass/greengrasssdk.h>
#include <iostream>
#include <string>
#include <memory>
#include <jansson.h>
#include <ctime>
#include <unistd.h>

class DeviceController {
private:
    std::unique_ptr<aws_greengrass_iot_data_client, decltype(&aws_greengrass_iot_data_client_destroy)> iot_client;
    
    static void message_callback_wrapper(const char *topic, const uint8_t *payload, 
                                        size_t payload_len, void *user_data) {
        auto* controller = static_cast<DeviceController*>(user_data);
        controller->on_cloud_command(topic, payload, payload_len);
    }
    
    std::string get_device_status() {
        // Simulate getting device status.
        return "online";
    }

public:
    DeviceController() 
        : iot_client(aws_greengrass_iot_data_client_new(), 
                     aws_greengrass_iot_data_client_destroy) {
        if (!iot_client) {
            throw std::runtime_error("Failed to create Greengrass IoT client");
        }
    }
    
    void on_cloud_command(const char *topic, const uint8_t *payload, size_t payload_len) {
        // Parse incoming command from IoT Core.
        std::string payload_str(reinterpret_cast<const char*>(payload), payload_len);
        
        json_error_t error;
        json_t *event = json_loads(payload_str.c_str(), 0, &error);
        
        if (!event) {
            std::cerr << "Error parsing JSON: " << error.text << std::endl;
            return;
        }
        
        // Extract command and device_id.
        json_t *command_obj = json_object_get(event, "command");
        json_t *device_id_obj = json_object_get(event, "device_id");
        
        const char *command = json_string_value(command_obj);
        const char *device_id = device_id_obj ? json_string_value(device_id_obj) : "device1";
        
        std::cout << "Received command from cloud: " << command << std::endl;
        
        // Process command.
        if (command && std::string(command) == "get_status") {
            std::string status = get_device_status();
            
            // Send telemetry back to IoT Core.
            json_t *telemetry_data = json_object();
            json_object_set_new(telemetry_data, "device_id", json_string(device_id));
            json_object_set_new(telemetry_data, "status", json_string(status.c_str()));
            json_object_set_new(telemetry_data, "timestamp", json_real(std::time(nullptr)));
            
            char *telemetry_payload = json_dumps(telemetry_data, JSON_COMPACT);
            
            // Publish telemetry to IoT Core.
            std::string telemetry_topic = "telemetry/" + std::string(device_id);
            
            aws_greengrass_publish_params params = {
                .topic = telemetry_topic.c_str(),
                .payload = reinterpret_cast<uint8_t*>(telemetry_payload),
                .payload_len = strlen(telemetry_payload)
            };
            
            aws_greengrass_iot_data_publish(iot_client.get(), &params);
            
            std::cout << "Telemetry sent to cloud: " << telemetry_payload << std::endl;
            
            free(telemetry_payload);
            json_decref(telemetry_data);
        }
        
        json_decref(event);
    }
    
    void subscribe_to_topic(const std::string& topic) {
        aws_greengrass_subscribe_params subscribe_params = {
            .topic = topic.c_str(),
            .callback = message_callback_wrapper,
            .user_data = this
        };
        
        aws_greengrass_iot_data_subscribe(iot_client.get(), &subscribe_params);
        
        std::cout << "Device Controller Lambda started" << std::endl;
        std::cout << "Subscribed to " << topic << std::endl;
        std::cout << "Waiting for commands from IoT Core..." << std::endl;
    }
    
    void run() {
        // Keep the Lambda running.
        while (true) {
            sleep(1);
        }
    }
};

int main(int argc, char *argv[]) {
    try {
        DeviceController controller;
        controller.subscribe_to_topic("commands/device1");
        controller.run();
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}
```

------

#### 汎用コンポーネント (V2)
<a name="lite-example-2-v2-code"></a>

で同じ機能を実現するには AWS IoT Greengrass V2、以下を使用して汎用コンポーネントを作成します。

##### 1. コンポーネントコード
<a name="lite-example-2-component-code"></a>

------
#### [ Python ]

前提条件: このコンポーネントコードを使用する前に、Greengrass デバイスに AWS IoT Device SDK for Python をインストールして検証します。

```
# Install the SDK
pip3 install awsiotsdk

# Verify installation
python3 -c "import awsiot.greengrasscoreipc.clientv2; print('SDK installed successfully')"
```

インストール中に依存関係の競合が発生した場合は、 の特定のバージョンをインストールしてみてください AWS IoT Device SDK。

検証コマンドで「SDK が正常にインストールされました」と表示される場合は、コンポーネントコードを使用する準備が整います。

```
from awsiot.greengrasscoreipc.clientv2 import GreengrassCoreIPCClientV2
from awsiot.greengrasscoreipc.model import QOS
import json
import time

ipc_client = GreengrassCoreIPCClientV2()

def on_command(event):
    """
    Receives commands from IoT Core,
    processes them, and sends telemetry back to cloud
    """
    try:
        # Receive command from IoT Core.
        data = json.loads(event.message.payload.decode('utf-8'))
        command = data.get('command')
        device_id = data.get('device_id', 'device1')

        print(f"Received command from cloud: {command}")

        # Process command.
        if command == 'get_status':
            status = get_device_status()

            # Send telemetry back to IoT Core.
            telemetry_data = {
                'device_id': device_id,
                'status': status,
                'timestamp': time.time()
            }

            ipc_client.publish_to_iot_core(
                topic_name=f'telemetry/{device_id}',
                qos=QOS.AT_LEAST_ONCE,
                payload=json.dumps(telemetry_data).encode('utf-8')
            )

            print(f"Telemetry sent to cloud: {telemetry_data}")

    except Exception as e:
        print(f"Error processing command: {e}")

def get_device_status():
    """Get current device status"""
    # Simulate getting device status.
    return 'online'

def main():
    print("Device Controller component starting...")

    # Subscribe to commands from IoT Core.
    ipc_client.subscribe_to_iot_core(
        topic_name='commands/device1',
        qos=QOS.AT_LEAST_ONCE,
        on_stream_event=on_command
    )

    print("Subscribed to commands/device1 from IoT Core")
    print("Waiting for commands from cloud...")

    # Keep running.
    while True:
        time.sleep(1)

if __name__ == '__main__':
    main()
```

------
#### [ Java ]

```
import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClientV2;
import software.amazon.awssdk.aws.greengrass.model.QOS;
import software.amazon.awssdk.aws.greengrass.model.SubscribeToIoTCoreRequest;
import software.amazon.awssdk.aws.greengrass.model.IoTCoreMessage;
import software.amazon.awssdk.aws.greengrass.model.PublishToIoTCoreRequest;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class DeviceController {
    private static GreengrassCoreIPCClientV2 ipcClient;

    public static void main(String[] args) {
        System.out.println("Device Controller component starting...");
        
        try (GreengrassCoreIPCClientV2 client = GreengrassCoreIPCClientV2.builder().build()) {
            ipcClient = client;

            SubscribeToIoTCoreRequest subscribeRequest = new SubscribeToIoTCoreRequest()
                .withTopicName("commands/device1")
                .withQos(QOS.AT_LEAST_ONCE);

            ipcClient.subscribeToIoTCore(
                subscribeRequest,
                DeviceController::onCommand,
                Optional.empty(),
                Optional.empty()
            );

            System.out.println("Subscribed to commands/device1 from IoT Core");
            System.out.println("Waiting for commands from cloud...");

            while (true) {
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public static void onCommand(IoTCoreMessage message) {
        try {
            String payload = new String(message.getMessage().getPayload(), StandardCharsets.UTF_8);
            
            // Simple JSON parsing.
            String command = extractJsonValue(payload, "command");
            String deviceId = extractJsonValue(payload, "device_id");
            if (deviceId == null || deviceId.isEmpty()) {
                deviceId = "device1";
            }

            System.out.println("Received command from cloud: " + command);

            if ("get_status".equals(command)) {
                String status = getDeviceStatus();

                // Build JSON manually.
                String telemetryJson = String.format(
                    "{\"device_id\":\"%s\",\"status\":\"%s\",\"timestamp\":%.3f}",
                    deviceId, status, System.currentTimeMillis() / 1000.0
                );
                byte[] telemetryBytes = telemetryJson.getBytes(StandardCharsets.UTF_8);

                PublishToIoTCoreRequest publishRequest = new PublishToIoTCoreRequest()
                    .withTopicName("telemetry/" + deviceId)
                    .withQos(QOS.AT_LEAST_ONCE)
                    .withPayload(telemetryBytes);

                ipcClient.publishToIoTCore(publishRequest);

                System.out.println("Telemetry sent to cloud: " + telemetryJson);
            }
        } catch (Exception e) {
            System.err.println("Error processing command: " + e.getMessage());
        }
    }

    private static String extractJsonValue(String json, String key) {
        Pattern pattern = Pattern.compile("\"" + Pattern.quote(key) + "\"\\s*:\\s*\"([^\"]+)\"");
        Matcher matcher = pattern.matcher(json);
        return matcher.find() ? matcher.group(1) : null;
    }

    private static String getDeviceStatus() {
        return "online";
    }
}
```

------
#### [ JavaScript ]

```
const greengrasscoreipc = require('aws-iot-device-sdk-v2').greengrasscoreipc;

class DeviceController {
    constructor() {
        this.ipcClient = null;
    }

    async start() {
        console.log('Device Controller component starting...');
        
        try {
            this.ipcClient = greengrasscoreipc.createClient();
            await this.ipcClient.connect();
            
            const subscribeRequest = {
                topicName: 'commands/device1',
                qos: 1
            };

            const streamingOperation = this.ipcClient.subscribeToIoTCore(subscribeRequest);
            
            streamingOperation.on('message', (message) => {
                this.onCommand(message);
            });
            
            streamingOperation.on('streamError', (error) => {
                console.error('Stream error:', error);
            });
            
            streamingOperation.on('ended', () => {
                console.log('Subscription stream ended');
            });
            
            await streamingOperation.activate();
            
            console.log('Subscribed to commands/device1 from IoT Core');
            console.log('Waiting for commands from cloud...');
            
        } catch (error) {
            console.error('Error starting component:', error);
            process.exit(1);
        }
    }

    async onCommand(message) {
        try {
            const payload = message.message.payload.toString('utf-8');
            const data = JSON.parse(payload);
            
            const command = data.command;
            const deviceId = data.device_id || 'device1';
            
            console.log(`Received command from cloud: ${command}`);
            
            if (command === 'get_status') {
                const status = this.getDeviceStatus();
                
                const telemetryData = {
                    device_id: deviceId,
                    status: status,
                    timestamp: Date.now() / 1000
                };
                
                const telemetryJson = JSON.stringify(telemetryData);
                
                const publishRequest = {
                    topicName: `telemetry/${deviceId}`,
                    qos: 1,
                    payload: Buffer.from(telemetryJson, 'utf-8')
                };
                
                await this.ipcClient.publishToIoTCore(publishRequest);
                console.log(`Telemetry sent to cloud: ${telemetryJson}`);
            }
            
        } catch (error) {
            console.error('Error processing command:', error);
        }
    }

    getDeviceStatus() {
        return 'online';
    }
}

// Start the component.
const controller = new DeviceController();
controller.start();
```

------
#### [ C ]

```
#include <gg/buffer.h>
#include <gg/error.h>
#include <gg/ipc/client.h>
#include <gg/map.h>
#include <gg/object.h>
#include <gg/sdk.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>

#define COMMAND_TOPIC "commands/device1"
#define TELEMETRY_TOPIC "telemetry/device1"

typedef struct {
    char device_id[64];
    char command[64];
} CommandData;

static pthread_mutex_t command_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t command_cond = PTHREAD_COND_INITIALIZER;
static CommandData pending_command;
static bool has_pending_command = false;

const char* get_device_status(void) {
    // Simulate getting device status.
    return "online";
}

static void *telemetry_publisher_thread(void *arg) {
    (void) arg;
    
    while (true) {
        pthread_mutex_lock(&command_mutex);
        while (!has_pending_command) {
            pthread_cond_wait(&command_cond, &command_mutex);
        }
        
        CommandData cmd = pending_command;
        has_pending_command = false;
        pthread_mutex_unlock(&command_mutex);
        
        // Process command.
        if (strcmp(cmd.command, "get_status") == 0) {
            const char *status = get_device_status();
            
            // Create telemetry JSON string.
            char telemetry_json[512];
            snprintf(telemetry_json, sizeof(telemetry_json),
                     "{\"device_id\":\"%s\",\"status\":\"%s\",\"timestamp\":%ld}",
                     cmd.device_id, status, time(NULL));
            
            GgBuffer telemetry_buf = {
                .data = (uint8_t *)telemetry_json,
                .len = strlen(telemetry_json)
            };
            
            // Publish telemetry to IoT Core.
            GgError ret = ggipc_publish_to_iot_core(GG_STR(TELEMETRY_TOPIC), telemetry_buf, 0);
            
            if (ret != GG_ERR_OK) {
                fprintf(stderr, "Failed to publish telemetry to IoT Core\n");
            } else {
                printf("Telemetry sent to cloud: device_id=%s, status=%s\n", cmd.device_id, status);
            }
        }
    }
    
    return NULL;
}

static void on_cloud_command(
    void *ctx, GgBuffer topic, GgBuffer payload, GgIpcSubscriptionHandle handle
) {
    (void) ctx;
    (void) topic;
    (void) handle;
    
    printf("Received command from IoT Core: %.*s\n", (int)payload.len, payload.data);
    
    // Parse JSON payload (comes as raw buffer from IoT Core).
    // For simplicity, we'll do basic string parsing.
    
    // Extract command and device_id from JSON string.
    char payload_str[512];
    snprintf(payload_str, sizeof(payload_str), "%.*s", (int)payload.len, payload.data);
    
    // Simple JSON parsing (looking for "command":"get_status").
    char *command_start = strstr(payload_str, "\"command\"");
    char *device_id_start = strstr(payload_str, "\"device_id\"");
    
    if (command_start) {
        pthread_mutex_lock(&command_mutex);
        
        char *cmd_value = strstr(command_start, ":");
        if (cmd_value) {
            cmd_value = strchr(cmd_value, '"');
            if (cmd_value) {
                cmd_value++;
                char *cmd_end = strchr(cmd_value, '"');
                if (cmd_end) {
                    size_t cmd_len = cmd_end - cmd_value;
                    if (cmd_len < sizeof(pending_command.command)) {
                        strncpy(pending_command.command, cmd_value, cmd_len);
                        pending_command.command[cmd_len] = '\0';
                    }
                }
            }
        }
        
        // Extract device_id or use default.
        if (device_id_start) {
            char *dev_value = strstr(device_id_start, ":");
            if (dev_value) {
                dev_value = strchr(dev_value, '"');
                if (dev_value) {
                    dev_value++;
                    char *dev_end = strchr(dev_value, '"');
                    if (dev_end) {
                        size_t dev_len = dev_end - dev_value;
                        if (dev_len < sizeof(pending_command.device_id)) {
                            strncpy(pending_command.device_id, dev_value, dev_len);
                            pending_command.device_id[dev_len] = '\0';
                        }
                    }
                }
            }
        } else {
            strcpy(pending_command.device_id, "device1");
        }
        
        printf("Received command from cloud: %s\n", pending_command.command);
        
        has_pending_command = true;
        pthread_cond_signal(&command_cond);
        pthread_mutex_unlock(&command_mutex);
    }
}

int main(void) {
    setvbuf(stdout, NULL, _IONBF, 0);
    printf("Device Controller component starting...\n");
    
    gg_sdk_init();
    
    GgError ret = ggipc_connect();
    if (ret != GG_ERR_OK) {
        fprintf(stderr, "Failed to connect to Greengrass nucleus\n");
        exit(1);
    }
    printf("Connected to Greengrass IPC\n");
    
    // Start telemetry publisher thread.
    pthread_t telemetry_thread;
    if (pthread_create(&telemetry_thread, NULL, telemetry_publisher_thread, NULL) != 0) {
        fprintf(stderr, "Failed to create telemetry publisher thread\n");
        exit(1);
    }
    
    // Subscribe to commands from IoT Core.
    GgIpcSubscriptionHandle handle;
    ret = ggipc_subscribe_to_iot_core(
        GG_STR(COMMAND_TOPIC),
        0,
        &on_cloud_command,
        NULL,
        &handle
    );
    
    if (ret != GG_ERR_OK) {
        fprintf(stderr, "Failed to subscribe to IoT Core topic\n");
        exit(1);
    }
    
    printf("Subscribed to %s\n", COMMAND_TOPIC);
    printf("Waiting for commands from IoT Core...\n");
    
    while (true) {
        sleep(1);
    }
    
    return 0;
}
```

------
#### [ C\$1\$1 ]

```
#include <gg/ipc/client.hpp>
#include <gg/buffer.hpp>
#include <gg/object.hpp>
#include <gg/types.hpp>

#include <chrono>
#include <condition_variable>
#include <ctime>
#include <iostream>
#include <mutex>
#include <string>
#include <string_view>
#include <thread>

constexpr std::string_view COMMAND_TOPIC = "commands/device1";
constexpr std::string_view TELEMETRY_TOPIC = "telemetry/device1";

struct CommandData {
    std::string device_id;
    std::string command;
};

static std::mutex command_mutex;
static std::condition_variable command_cv;
static CommandData pending_command;
static bool has_pending_command = false;

std::string get_device_status() {
    // Simulate getting device status.
    return "online";
}

void telemetry_publisher_thread() {
    auto& client = gg::ipc::Client::get();
    
    while (true) {
        std::unique_lock<std::mutex> lock(command_mutex);
        command_cv.wait(lock, [] { return has_pending_command; });
        
        CommandData cmd = pending_command;
        has_pending_command = false;
        lock.unlock();
        
        // Process command.
        if (cmd.command == "get_status") {
            std::string status = get_device_status();
            
            // Get current timestamp.
            auto now = std::time(nullptr);
            
            // Create telemetry JSON payload.
            std::string telemetry_payload = "{\"device_id\":\"" + cmd.device_id + 
                                          "\",\"status\":\"" + status + 
                                          "\",\"timestamp\":" + std::to_string(now) + "}";
            
            // Publish telemetry to IoT Core.
            gg::Buffer telemetry_buffer(telemetry_payload);
            auto error = client.publish_to_iot_core(TELEMETRY_TOPIC, telemetry_buffer);
            
            if (error) {
                std::cerr << "Failed to publish telemetry to IoT Core: " 
                         << error.message() << std::endl;
            } else {
                std::cout << "Telemetry sent to cloud: device_id=" << cmd.device_id 
                         << ", status=" << status << std::endl;
            }
        }
    }
}

class CloudCommandCallback : public gg::ipc::IoTCoreTopicCallback {
    void operator()(
        std::string_view topic,
        gg::Object payload,
        gg::ipc::Subscription& handle
    ) override {
        (void) topic;
        (void) handle;
        
        // Payload is a Buffer containing JSON string from IoT Core.
        if (payload.index() != GG_TYPE_BUF) {
            std::cerr << "Expected Buffer message\n";
            return;
        }
        
        // Extract buffer.
        auto buffer = gg::get<std::span<uint8_t>>(payload);
        std::string json_str(reinterpret_cast<const char*>(buffer.data()), buffer.size());
        
        std::cout << "Received command from IoT Core: " << json_str << std::endl;
        
        // Simple JSON parsing for demo.
        std::string command;
        std::string device_id = "device1";  // Default
        
        // Extract command.
        size_t cmd_pos = json_str.find("\"command\":");
        if (cmd_pos != std::string::npos) {
            size_t start = json_str.find("\"", cmd_pos + 10) + 1;
            size_t end = json_str.find("\"", start);
            if (end != std::string::npos) {
                command = json_str.substr(start, end - start);
            }
        }
        
        // Extract device_id if present.
        size_t dev_pos = json_str.find("\"device_id\":");
        if (dev_pos != std::string::npos) {
            size_t start = json_str.find("\"", dev_pos + 12) + 1;
            size_t end = json_str.find("\"", start);
            if (end != std::string::npos) {
                device_id = json_str.substr(start, end - start);
            }
        }
        
        if (!command.empty()) {
            std::lock_guard<std::mutex> lock(command_mutex);
            pending_command = {device_id, command};
            has_pending_command = true;
            command_cv.notify_one();
            
            std::cout << "Received command from cloud: " << command << std::endl;
        }
    }
};

int main() {
    // Disable stdout buffering for real-time logging in systemd/Greengrass.
    std::cout.setf(std::ios::unitbuf);
    
    std::cout << "Device Controller component starting..." << std::endl;
    
    auto& client = gg::ipc::Client::get();
    
    auto error = client.connect();
    if (error) {
        std::cerr << "Failed to connect to Greengrass nucleus: " 
                 << error.message() << std::endl;
        return 1;
    }
    
    std::cout << "Connected to Greengrass IPC" << std::endl;
    
    // Start telemetry publisher thread.
    std::thread telemetry_thread(telemetry_publisher_thread);
    telemetry_thread.detach();
    
    // Subscribe to commands from IoT Core.
    static CloudCommandCallback handler;
    error = client.subscribe_to_iot_core(COMMAND_TOPIC, handler);
    
    if (error) {
        std::cerr << "Failed to subscribe to IoT Core topic: " 
                 << error.message() << std::endl;
        return 1;
    }
    
    std::cout << "Subscribed to " << COMMAND_TOPIC << std::endl;
    std::cout << "Waiting for commands from IoT Core..." << std::endl;
    
    // Keep running.
    while (true) {
        using namespace std::chrono_literals;
        std::this_thread::sleep_for(1s);
    }
    
    return 0;
}
```

------

##### 2. コンポーネントの構築とパッケージ化
<a name="lite-example-2-build-component"></a>

一部の言語では、デプロイ前に構築またはパッケージ化が必要です。

------
#### [ Python ]

Python ではコンパイルは必要ありません。コンポーネントは .py ファイルを直接使用できます。

------
#### [ Java ]

すべての依存関係がバンドルされた実行可能 JAR を構築するには:

1. プロジェクトディレクトリに `pom.xml` ファイルを作成します。

   ```
   <?xml version="1.0" encoding="UTF-8"?>
   <project xmlns="http://maven.apache.org/POM/4.0.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
   
       <!-- Basic project information: organization, component name, and version -->
       <groupId>com.example</groupId>
       <artifactId>device-controller</artifactId>
       <version>1.0.0</version>
   
       <properties>
           <!-- Java 11 LTS (Long Term Support) is recommended for Greengrass v2 components -->
           <maven.compiler.source>11</maven.compiler.source>
           <maven.compiler.target>11</maven.compiler.target>
       </properties>
   
       <dependencies>
           <!-- AWS IoT Device SDK for Java - provides IPC client for Greengrass v2 cloud communication -->
           <dependency>
               <groupId>software.amazon.awssdk.iotdevicesdk</groupId>
               <artifactId>aws-iot-device-sdk</artifactId>
               <version>1.25.1</version>
           </dependency>
       </dependencies>
   
       <build>
           <plugins>
               <!-- Maven Shade Plugin - creates a standalone JAR with all dependencies included for Greengrass deployment -->
               <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-shade-plugin</artifactId>
                   <version>3.2.4</version>
                   <executions>
                       <execution>
                           <phase>package</phase>
                           <goals>
                               <goal>shade</goal>
                           </goals>
                           <configuration>
                               <transformers>
                                   <!-- Set the main class for the executable JAR -->
                                   <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                       <mainClass>DeviceController</mainClass>
                                   </transformer>
                               </transformers>
                               <filters>
                                   <!-- Exclude signature files to avoid security exceptions -->
                                   <filter>
                                       <artifact>*:*</artifact>
                                       <excludes>
                                           <exclude>META-INF/*.SF</exclude>
                                           <exclude>META-INF/*.DSA</exclude>
                                           <exclude>META-INF/*.RSA</exclude>
                                       </excludes>
                                   </filter>
                               </filters>
                           </configuration>
                       </execution>
                   </executions>
               </plugin>
           </plugins>
       </build>
   </project>
   ```

1. JAR を構築します。

   ```
   mvn clean package
   ```

   これにより、すべての依存関係を含む `target/device-controller-1.0.0.jar` が作成されます。

1. デプロイのために JAR を S3 バケットにアップロードします。

------
#### [ JavaScript ]

Node.js コンポーネントをすべての依存関係でパッケージ化するには:

1. `package.json` ファイルを作成します。

   ```
   {
     "name": "device-controller",
     "version": "1.0.0",
     "description": "Device controller component for Greengrass v2",
     "main": "DeviceController.js",
     "dependencies": {
       "aws-iot-device-sdk-v2": "^1.21.0"
     },
     "engines": {
       "node": ">=14.0.0"
     }
   }
   ```

1. 開発マシンに依存関係をインストールします。

   ```
   npm install
   ```

   これにより、v2 AWS AWS IoT Device SDK を含む`node_modules`フォルダが作成されます。

1. デプロイ用のパッケージ:

   ```
   zip -r DeviceController.zip DeviceController.js node_modules/ package.json
   ```

1. zip ファイルを S3 バケットにアップロードしてデプロイします。

**注記**  
Greengrass デバイスには Node.js ランタイムがインストールされている必要があります (バージョン 14 以降）。コンポーネントアーティファクト`npm install`にはバンドルされた`node_modules`フォルダ内のすべての依存関係が含まれているため、Greengrass コアデバイスで を実行する必要はありません。

------
#### [ C ]

**前提条件**:

SDK と コンポーネントを構築するには、次のビルド依存関係が必要です。
+ GCC または Clang
+ CMake (バージョン 3.22 以上)
+ または Ninja を作成する

**ビルドの依存関係をインストールします。**

Ubuntu/Debian の場合:

```
sudo apt install build-essential cmake
```

Amazon Linux で

```
sudo yum install gcc cmake make
```

**コンポーネントの CMakeLists.txt ファイルを作成します。**

```
cmake_minimum_required(VERSION 3.10)
project(DeviceController C)

set(CMAKE_C_STANDARD 11)

# Add AWS Greengrass Component SDK
add_subdirectory(aws-greengrass-component-sdk)

# Build your component executable
add_executable(device_controller device_controller.c)
target_link_libraries(device_controller gg-sdk)
```

**ビルドステップ:**

```
# Clone the AWS Greengrass Component SDK into your project
git clone https://github.com/aws-greengrass/aws-greengrass-component-sdk.git

# Build your component
cmake -B build -D CMAKE_BUILD_TYPE=MinSizeRel
make -C build -j$(nproc)

# The binary 'device_controller' is in ./build/
# Upload this binary to S3 for deployment
```

------
#### [ C\$1\$1 ]

**前提条件**:

SDK と コンポーネントを構築するには、次のビルド依存関係が必要です。
+ C\$1\$120 をサポートする GCC または Clang
+ CMake (バージョン 3.22 以上)
+ または Ninja を作成する

**ビルドの依存関係をインストールします。**

Ubuntu/Debian の場合:

```
sudo apt install build-essential cmake
```

Amazon Linux で

```
sudo yum install gcc-c++ cmake make
```

**コンポーネントの CMakeLists.txt ファイルを作成します。**

```
cmake_minimum_required(VERSION 3.10)
project(DeviceController CXX)

set(CMAKE_CXX_STANDARD 20)

# Add SDK as subdirectory
add_subdirectory(aws-greengrass-component-sdk)

# Add C++ SDK subdirectory
add_subdirectory(aws-greengrass-component-sdk/cpp)

add_executable(device_controller device_controller.cpp)
target_link_libraries(device_controller gg-sdk++)
```

**ビルドステップ:**

```
# Clone the AWS Greengrass Component SDK into your project
git clone https://github.com/aws-greengrass/aws-greengrass-component-sdk.git

# Build your component
cmake -B build -D CMAKE_BUILD_TYPE=MinSizeRel
make -C build -j$(nproc)

# The binary 'device_controller' will be in ./build/
# Upload this binary to S3 for deployment
```

------

##### 3. コンポーネントレシピ
<a name="lite-example-2-component-recipe"></a>

コンポーネントが使用する実際のトピックで「リソース」配列を更新します。

------
#### [ Python ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.DeviceController",
  "ComponentVersion": "1.0.0",
  "ComponentType": "aws.greengrass.generic",
  "ComponentDescription": "Receives commands from IoT Core and sends telemetry back to cloud",
  "ComponentPublisher": "[Your Company]",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.DeviceController:mqttproxy:1": {
            "policyDescription": "Allows access to subscribe to IoT Core topics",
            "operations": [
              "aws.greengrass#SubscribeToIoTCore"
            ],
            "resources": [
              "commands/device1"
            ]
          },
          "com.example.DeviceController:mqttproxy:2": {
            "policyDescription": "Allows access to publish to IoT Core topics",
            "operations": [
              "aws.greengrass#PublishToIoTCore"
            ],
            "resources": [
              "telemetry/device1"
            ]
          }
        }
      }
    }
  },
  "ComponentDependencies": {
    "aws.greengrass.TokenExchangeService": {
      "VersionRequirement": ">=2.0.0",
      "DependencyType": "HARD"
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "python3 -u {artifacts:path}/device_controller.py"
      },
      "Artifacts": [
        {
          "Uri": "s3://YOUR-BUCKET/artifacts/com.example.DeviceController/1.0.0/device_controller.py"
        }
      ]
    }
  ]
}
```

------
#### [ Java ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.DeviceController",
  "ComponentVersion": "1.0.0",
  "ComponentType": "aws.greengrass.generic",
  "ComponentDescription": "Receives commands from IoT Core and sends telemetry back to cloud",
  "ComponentPublisher": "[Your Company]",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.DeviceController:mqttproxy:1": {
            "policyDescription": "Allows access to subscribe to IoT Core topics",
            "operations": [
              "aws.greengrass#SubscribeToIoTCore"
            ],
            "resources": [
              "commands/device1"
            ]
          },
          "com.example.DeviceController:mqttproxy:2": {
            "policyDescription": "Allows access to publish to IoT Core topics",
            "operations": [
              "aws.greengrass#PublishToIoTCore"
            ],
            "resources": [
              "telemetry/device1"
            ]
          }
        }
      }
    }
  },
  "ComponentDependencies": {
    "aws.greengrass.TokenExchangeService": {
      "VersionRequirement": ">=2.0.0",
      "DependencyType": "HARD"
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "java -jar {artifacts:path}/DeviceController.jar"
      },
      "Artifacts": [
        {
          "Uri": "s3://YOUR-BUCKET/artifacts/com.example.DeviceController/1.0.0/DeviceController.jar"
        }
      ]
    }
  ]
}
```

------
#### [ JavaScript ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.DeviceController",
  "ComponentVersion": "1.0.0",
  "ComponentType": "aws.greengrass.generic",
  "ComponentDescription": "Receives commands from IoT Core and sends telemetry back to cloud",
  "ComponentPublisher": "[Your Company]",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.DeviceController:mqttproxy:1": {
            "policyDescription": "Allows access to subscribe to command topics from IoT Core",
            "operations": [
              "aws.greengrass#SubscribeToIoTCore"
            ],
            "resources": [
              "commands/device1"
            ]
          },
          "com.example.DeviceController:mqttproxy:2": {
            "policyDescription": "Allows access to publish telemetry to IoT Core",
            "operations": [
              "aws.greengrass#PublishToIoTCore"
            ],
            "resources": [
              "telemetry/*"
            ]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "cd {artifacts:decompressedPath}/DeviceController && node DeviceController.js"
      },
      "Artifacts": [
        {
          "Uri": "s3://YOUR-BUCKET/artifacts/com.example.DeviceController/1.0.0/DeviceController.zip",
          "Unarchive": "ZIP"
        }
      ]
    }
  ]
}
```

------
#### [ C/C\$1\$1 ]

```
{
  "RecipeFormatVersion": "2020-01-25",
  "ComponentName": "com.example.DeviceController",
  "ComponentVersion": "1.0.0",
  "ComponentType": "aws.greengrass.generic",
  "ComponentDescription": "Receives commands from IoT Core and sends telemetry back to cloud",
  "ComponentPublisher": "[Your Company]",
  "ComponentConfiguration": {
    "DefaultConfiguration": {
      "accessControl": {
        "aws.greengrass.ipc.mqttproxy": {
          "com.example.DeviceController:mqttproxy:1": {
            "policyDescription": "Allows access to subscribe to IoT Core topics",
            "operations": ["aws.greengrass#SubscribeToIoTCore"],
            "resources": ["commands/device1"]
          },
          "com.example.DeviceController:mqttproxy:2": {
            "policyDescription": "Allows access to publish to IoT Core topics",
            "operations": ["aws.greengrass#PublishToIoTCore"],
            "resources": ["telemetry/device1"]
          }
        }
      }
    }
  },
  "Manifests": [
    {
      "Platform": {
        "os": "linux",
        "runtime": "*"
      },
      "Lifecycle": {
        "run": "{artifacts:path}/device_controller"
      },
      "Artifacts": [
        {
          "Uri": "s3://YOUR-BUCKET/artifacts/com.example.DeviceController/1.0.0/device_controller"
        }
      ]
    }
  ]
}
```

------