ローカルシャドウとやり取り - AWS IoT Greengrass

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

ローカルシャドウとやり取り

シャドウ IPC サービスを使用して、デバイスのローカルシャドウとやり取りします。やり取りするデバイスには、コアデバイスまたは接続されたクライアントデバイスを選択できます。

​これらの IPC オペレーションを使用するには、シャドウマネージャーコンポーネントをカスタムコンポーネントの依存関係として含めます。その後、カスタムコンポーネントの IPC オペレーションを使用して、シャドウマネージャーを介してデバイスのローカルシャドウとやり取りできます。カスタムコンポーネントがローカルシャドウの状態の変更に対応できるようにするには、パブリッシュ/サブスクライブ IPC サービスを使用して、シャドウイベントをサブスクライブすることもできます。パブリッシュ/サブスクライブサービスの使用の詳細については、「ローカルメッセージをパブリッシュ/サブスクライブする」を参照してください。

注記

コアデバイスがクライアントデバイスシャドウとやり取りできるようにするには、MQTT ブリッジコンポーネントを設定してデプロイする必要もあります。詳細については、「Enable shadow manager to communicate with client devices」(シャドウマネージャーがクライアントデバイスと通信できるようにする) を参照してください。

最小 SDK バージョン

以下の表に AWS IoT Device SDK の最小バージョンを示します。ローカルシャドウとやり取りする際は、これを使用する必要があります。

認証

カスタムコンポーネントでシャドウ IPC サービスを使用するには、コンポーネントがシャドウとやり取りできるように承認ポリシーを定義する必要があります。承認ポリシーの定義については、「コンポーネントにIPCオペレーションの実行を許可する」を参照してください。

シャドウ操作の承認ポリシーには以下のプロパティがあります。

IPC サービス識別子: aws.greengrass.ShadowManager

操作 説明 リソース

aws.greengrass#GetThingShadow

コンポーネントがモノのシャドウを取得できるようにします。

次の文字列のいずれか。

  • $aws/things/thingName/shadow/ は、クラシックデバイスシャドウへのアクセスを許可します。

  • $aws/things/thingName/shadow/name/shadowName は、名前付きシャドウへのアクセスを許可します。

  • * は、すべてのシャドウへのアクセスを許可します。

aws.greengrass#UpdateThingShadow

コンポーネントがモノのシャドウを更新できるようにします。

次の文字列のいずれか。

  • $aws/things/thingName/shadow/ は、クラシックデバイスシャドウへのアクセスを許可します。

  • $aws/things/thingName/shadow/name/shadowName は、名前付きシャドウへのアクセスを許可します。

  • * は、すべてのシャドウへのアクセスを許可します。

aws.greengrass#DeleteThingShadow

コンポーネントがモノのシャドウを削除できるようにします。

次の文字列のいずれか。

  • $aws/things/thingName/shadow/ は、クラシックデバイスシャドウへのアクセスを許可します。

  • $aws/things/thingName/shadow/name/shadowName は、名前付きシャドウへのアクセスを許可します。

  • * は、すべてのシャドウへのアクセスを許可します。

aws.greengrass#ListNamedShadowsForThing

コンポーネントがモノの名前付きシャドウのリストを取得できるようにします。

モノにアクセスしてそのシャドウを一覧表示できるようにするモノの名前の文字列。

* を使用してすべてのモノへのアクセスを許可します。

IPC サービス識別子: aws.greengrass.ipc.pubsub

操作 説明 リソース

aws.greengrass#SubscribeToTopic

コンポーネントが、指定したトピックに関するメッセージをサブスクライブできるようにします。

次のトピック文字列のいずれか。

  • shadowTopicPrefix/get/accepted

  • shadowTopicPrefix/get/rejected

  • shadowTopicPrefix/delete/accepted

  • shadowTopicPrefix/delete/rejected

  • shadowTopicPrefix/update/accepted

  • shadowTopicPrefix/update/delta

  • shadowTopicPrefix/update/rejected

トピック接頭辞 shadowTopicPrefix の値は、以下に挙げるシャドウのタイプに応じて変化します。

  • クラシックシャドウ: $aws/things/thingName/shadow

  • 名前付きシャドウ: $aws/things/thingName/shadow/name/shadowName

すべてのトピックへのアクセスを許可するには、* を使用します。

Greengrass nucleus v2.6.0 以降では、MQTT トピックワイルドカード (# および +) を含むトピックをサブスクライブできます。このトピック文字列は MQTT トピックのワイルドカードを文字そのものとしてサポートします。例えば、コンポーネントの承認ポリシーで test/topic/# へのアクセス権が付与されている場合、コンポーネントは test/topic/# をサブスクライブできますが、test/topic/filter はサブスクライブできません。

ローカルシャドウ承認ポリシーのレシピ変数

Greengrass nucleus の v2.6.0 以降を使用していて、Greengrass nucleus interpolateComponentConfigurationの設定オプションを に設定した場合はtrue、承認ポリシーで {iot:thingName} recipe 変数を使用できます。この機能を使用すると、コアデバイスのグループに対して 1 つの承認ポリシーを設定できます。各コアデバイスは自身のシャドウにのみアクセスできます。例えば、シャドウ IPC オペレーションのために、コンポーネントに次のリソースへのアクセスを許可することができます。

$aws/things/{iot:thingName}/shadow/

承認ポリシーの例

次の承認ポリシーの例を参照して、コンポーネントの承認ポリシー設定の参考にできます。

例: コアデバイスのグループがローカルシャドウとやり取りすることを許可する
重要

この例では、機能は、Greengrass nucleus コンポーネントの v2.6.0 以降で利用できる機能を使用しています。Greengrass nucleus v2.6.0 では、コンポーネント設定に、ほとんどの recipe 変数 ({iot:thingName} など) のサポートが追加されました。この機能を有効にするには、Greengrass nucleus interpolateComponentConfigurationの設定オプションを に設定しますtrueGreengrass nucleus のすべてのバージョンで機能する例については、「example authorization policy for a single core device」(シングルコアデバイスの承認ポリシーの例) を参照してください。

次の承認ポリシーの例では、コンポーネント com.example.MyShadowInteractionComponent がクラシックデバイスシャドウ、およびコンポーネントを実行しているコアデバイスの名前付きシャドウ myNamedShadow とやり取りできるようにします。このポリシーは、このコンポーネントがこれらのシャドウのローカルトピックに関するメッセージを受信できるようにもします。

JSON
{ "accessControl": { "aws.greengrass.ShadowManager": { "com.example.MyShadowInteractionComponent:shadow:1": { "policyDescription": "Allows access to shadows", "operations": [ "aws.greengrass#GetThingShadow", "aws.greengrass#UpdateThingShadow", "aws.greengrass#DeleteThingShadow" ], "resources": [ "$aws/things/{iot:thingName}/shadow", "$aws/things/{iot:thingName}/shadow/name/myNamedShadow" ] }, "com.example.MyShadowInteractionComponent:shadow:2": { "policyDescription": "Allows access to things with shadows", "operations": [ "aws.greengrass#ListNamedShadowsForThing" ], "resources": [ "{iot:thingName}" ] } }, "aws.greengrass.ipc.pubsub": { "com.example.MyShadowInteractionComponent:pubsub:1": { "policyDescription": "Allows access to shadow pubsub topics", "operations": [ "aws.greengrass#SubscribeToTopic" ], "resources": [ "$aws/things/{iot:thingName}/shadow/get/accepted", "$aws/things/{iot:thingName}/shadow/name/myNamedShadow/get/accepted" ] } } } }
YAML
accessControl: aws.greengrass.ShadowManager: 'com.example.MyShadowInteractionComponent:shadow:1': policyDescription: 'Allows access to shadows' operations: - 'aws.greengrass#GetThingShadow' - 'aws.greengrass#UpdateThingShadow' - 'aws.greengrass#DeleteThingShadow' resources: - $aws/things/{iot:thingName}/shadow - $aws/things/{iot:thingName}/shadow/name/myNamedShadow 'com.example.MyShadowInteractionComponent:shadow:2': policyDescription: 'Allows access to things with shadows' operations: - 'aws.greengrass#ListNamedShadowsForThing' resources: - '{iot:thingName}' aws.greengrass.ipc.pubsub: 'com.example.MyShadowInteractionComponent:pubsub:1': policyDescription: 'Allows access to shadow pubsub topics' operations: - 'aws.greengrass#SubscribeToTopic' resources: - $aws/things/{iot:thingName}/shadow/get/accepted - $aws/things/{iot:thingName}/shadow/name/myNamedShadow/get/accepted
例: コアデバイスのグループがクライアントデバイスシャドウとやり取りすることを許可する
重要

この機能には、Greengrass nucleus v2.6.0 以降、シャドウマネージャー v2.2.0 以降、および MQTT ブリッジ v2.2.0 以降が必要です。シャドウマネージャーがクライアントデバイスと通信できるように MQTT ブリッジを設定する必要があります。

次の承認ポリシーの例では、コンポーネント com.example.MyShadowInteractionComponent が、名前が MyClientDevice で始まるクライアントデバイスのすべてのデバイスシャドウとやり取りできるようにします。

注記

コアデバイスがクライアントデバイスシャドウとやり取りできるようにするには、MQTT ブリッジコンポーネントを設定してデプロイする必要もあります。詳細については、「Enable shadow manager to communicate with client devices」(シャドウマネージャーがクライアントデバイスと通信できるようにする) を参照してください。

JSON
{ "accessControl": { "aws.greengrass.ShadowManager": { "com.example.MyShadowInteractionComponent:shadow:1": { "policyDescription": "Allows access to shadows", "operations": [ "aws.greengrass#GetThingShadow", "aws.greengrass#UpdateThingShadow", "aws.greengrass#DeleteThingShadow" ], "resources": [ "$aws/things/MyClientDevice*/shadow", "$aws/things/MyClientDevice*/shadow/name/*" ] }, "com.example.MyShadowInteractionComponent:shadow:2": { "policyDescription": "Allows access to things with shadows", "operations": [ "aws.greengrass#ListNamedShadowsForThing" ], "resources": [ "MyClientDevice*" ] } } } }
YAML
accessControl: aws.greengrass.ShadowManager: 'com.example.MyShadowInteractionComponent:shadow:1': policyDescription: 'Allows access to shadows' operations: - 'aws.greengrass#GetThingShadow' - 'aws.greengrass#UpdateThingShadow' - 'aws.greengrass#DeleteThingShadow' resources: - $aws/things/MyClientDevice*/shadow - $aws/things/MyClientDevice*/shadow/name/* 'com.example.MyShadowInteractionComponent:shadow:2': policyDescription: 'Allows access to things with shadows' operations: - 'aws.greengrass#ListNamedShadowsForThing' resources: - MyClientDevice*
例: シングルコアデバイスがローカルシャドウとやり取りすることを許可する

以下の承認ポリシーの例は、コンポーネント com.example.MyShadowInteractionComponent がクラシックデバイスシャドウ、およびデバイス MyThingName の名前付きシャドウ myNamedShadow とやり取りできるようにします。このポリシーは、このコンポーネントがこれらのシャドウのローカルトピックに関するメッセージを受信できるようにもします。

JSON
{ "accessControl": { "aws.greengrass.ShadowManager": { "com.example.MyShadowInteractionComponent:shadow:1": { "policyDescription": "Allows access to shadows", "operations": [ "aws.greengrass#GetThingShadow", "aws.greengrass#UpdateThingShadow", "aws.greengrass#DeleteThingShadow" ], "resources": [ "$aws/things/MyThingName/shadow", "$aws/things/MyThingName/shadow/name/myNamedShadow" ] }, "com.example.MyShadowInteractionComponent:shadow:2": { "policyDescription": "Allows access to things with shadows", "operations": [ "aws.greengrass#ListNamedShadowsForThing" ], "resources": [ "MyThingName" ] } }, "aws.greengrass.ipc.pubsub": { "com.example.MyShadowInteractionComponent:pubsub:1": { "policyDescription": "Allows access to shadow pubsub topics", "operations": [ "aws.greengrass#SubscribeToTopic" ], "resources": [ "$aws/things/MyThingName/shadow/get/accepted", "$aws/things/MyThingName/shadow/name/myNamedShadow/get/accepted" ] } } } }
YAML
accessControl: aws.greengrass.ShadowManager: 'com.example.MyShadowInteractionComponent:shadow:1': policyDescription: 'Allows access to shadows' operations: - 'aws.greengrass#GetThingShadow' - 'aws.greengrass#UpdateThingShadow' - 'aws.greengrass#DeleteThingShadow' resources: - $aws/things/MyThingName/shadow - $aws/things/MyThingName/shadow/name/myNamedShadow 'com.example.MyShadowInteractionComponent:shadow:2': policyDescription: 'Allows access to things with shadows' operations: - 'aws.greengrass#ListNamedShadowsForThing' resources: - MyThingName aws.greengrass.ipc.pubsub: 'com.example.MyShadowInteractionComponent:pubsub:1': policyDescription: 'Allows access to shadow pubsub topics' operations: - 'aws.greengrass#SubscribeToTopic' resources: - $aws/things/MyThingName/shadow/get/accepted - $aws/things/MyThingName/shadow/name/myNamedShadow/get/accepted
例: コアデバイスのグループがローカルシャドウの状態変化に反応することを許可する
重要

この例では、機能は、Greengrass nucleus コンポーネントの v2.6.0 以降で利用できる機能を使用しています。Greengrass nucleus v2.6.0 では、コンポーネント設定に、ほとんどの recipe 変数 ({iot:thingName} など) のサポートが追加されました。この機能を有効にするには、Greengrass nucleus interpolateComponentConfigurationの設定オプションを に設定しますtrueGreengrass nucleus のすべてのバージョンで機能する例については、「example authorization policy for a single core device」(シングルコアデバイスの承認ポリシーの例) を参照してください。

次のアクセスコントロールポリシーの例では、クラシックデバイスシャドウおよび名前付きシャドウ myNamedShadow/update/delta トピックに関するメッセージを、コンポーネントを実行している各コアデバイスで、カスタム com.example.MyShadowReactiveComponent が受信できるようにします。

JSON
{ "accessControl": { "aws.greengrass.ipc.pubsub": { "com.example.MyShadowReactiveComponent:pubsub:1": { "policyDescription": "Allows access to shadow pubsub topics", "operations": [ "aws.greengrass#SubscribeToTopic" ], "resources": [ "$aws/things/{iot:thingName}/shadow/update/delta", "$aws/things/{iot:thingName}/shadow/name/myNamedShadow/update/delta" ] } } } }
YAML
accessControl: aws.greengrass.ipc.pubsub: "com.example.MyShadowReactiveComponent:pubsub:1": policyDescription: Allows access to shadow pubsub topics operations: - 'aws.greengrass#SubscribeToTopic' resources: - $aws/things/{iot:thingName}/shadow/update/delta - $aws/things/{iot:thingName}/shadow/name/myNamedShadow/update/delta
例: シングルコアデバイスに、ローカルシャドウの状態の変化に反応することを許可する

次のアクセスコントロールポリシーの例では、デバイス MyThingName について、クラシックデバイスシャドウおよび名前付きシャドウ myNamedShadow/update/delta トピックに関するメッセージを、カスタム com.example.MyShadowReactiveComponent が受信できるようにします。

JSON
{ "accessControl": { "aws.greengrass.ipc.pubsub": { "com.example.MyShadowReactiveComponent:pubsub:1": { "policyDescription": "Allows access to shadow pubsub topics", "operations": [ "aws.greengrass#SubscribeToTopic" ], "resources": [ "$aws/things/MyThingName/shadow/update/delta", "$aws/things/MyThingName/shadow/name/myNamedShadow/update/delta" ] } } } }
YAML
accessControl: aws.greengrass.ipc.pubsub: "com.example.MyShadowReactiveComponent:pubsub:1": policyDescription: Allows access to shadow pubsub topics operations: - 'aws.greengrass#SubscribeToTopic' resources: - $aws/things/MyThingName/shadow/update/delta - $aws/things/MyThingName/shadow/name/myNamedShadow/update/delta

GetThingShadow

指定したモノのシャドウを取得します。

リクエスト

このオペレーションのリクエストには以下のパラメータがあります。

thingName (Python: thing_name)

モノの名前。

タイプ: string

shadowName (Python: shadow_name)

シャドウの名前。モノのクラシックシャドウを指定するには、このパラメータを空の文字列 ("") に設定します。

警告

AWS IoT Greengrass サービスは、AWSManagedGreengrassV2Deployment 名前付きシャドウを使用して、個々のコアデバイスを対象とするデプロイを管理します。この名前付きシャドウは、AWS IoT Greengrass サービスで使用するために予約されています。この名前付きシャドウを更新または削除しないでください。

タイプ: string

レスポンス

このオペレーションのレスポンスには以下の情報が含まれます。

payload

BLOB としてのレスポンス状態ドキュメント。

タイプ: 次の情報が含まれる object

state

状態情報。

このオブジェクトには、次の情報が含まれます。

desired

デバイスで更新がリクエストされた state のプロパティと値。

タイプ: キーバリューペアの map

reported

デバイスによってレポートされた state のプロパティと値。

タイプ: キーバリューペアの map

delta

望ましい state とレポートされた state のプロパティと値の違い。このプロパティは、desiredreported の state が異なる場合のみ存在します。

タイプ: キーバリューペアの map

metadata

いつ状態が更新されたか判別するための、desired および reported セクションの属性ごとのタイムスタンプ。

タイプ: string

timestamp

レスポンスが生成された日付と時刻 (エポック時間)。

タイプ: integer

clientToken (Python: clientToken)

リクエストとレスポンスを対応付けるために使用されるトークン

タイプ: string

version

ローカルシャドウドキュメントのバージョン。

タイプ: integer

エラー

このオペレーションは以下のエラーを返す場合があります。

InvalidArgumentsError

ローカルシャドウサービスは、リクエストパラメータを検証できません。これは、リクエストに不正な形式の JSON またはサポートされていない文字が含まれている場合に発生する可能性があります。

ResourceNotFoundError

要求されたローカルシャドウドキュメントが見つかりません。

ServiceError

内部サービスエラーが発生したか、IPC サービスへのリクエスト数が、シャドウマネージャーコンポーネントの maxLocalRequestsPerSecondPerThing および maxTotalLocalRequestsRate の設定パラメータで指定された制限を超えました。

UnauthorizedError

コンポーネントの承認ポリシーには、このオペレーションに必要な権限が含まれていません。

以下の例では、カスタムコンポーネントコードでこのオペレーションを呼び出す方法を示します。

Java (IPC client V1)
例: モノのシャドウを取得する
注記

この例は IPCUtils クラスを使用して、AWS IoT Greengrass Core IPC サービスへの接続を作成します。詳細については、「AWS IoT Greengrass Core IPCサービスに接続する」を参照してください。

package com.aws.greengrass.docs.samples.ipc; import com.aws.greengrass.docs.samples.ipc.util.IPCUtils; import software.amazon.awssdk.aws.greengrass.GetThingShadowResponseHandler; import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient; import software.amazon.awssdk.aws.greengrass.model.GetThingShadowRequest; import software.amazon.awssdk.aws.greengrass.model.GetThingShadowResponse; import software.amazon.awssdk.aws.greengrass.model.ResourceNotFoundError; import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError; import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection; import java.nio.charset.StandardCharsets; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class GetThingShadow { public static final int TIMEOUT_SECONDS = 10; public static void main(String[] args) { // Use the current core device's name if thing name isn't set. String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0]; String shadowName = args[1]; try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) { GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection); GetThingShadowResponseHandler responseHandler = GetThingShadow.getThingShadow(ipcClient, thingName, shadowName); CompletableFuture<GetThingShadowResponse> futureResponse = responseHandler.getResponse(); try { GetThingShadowResponse response = futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); String shadowPayload = new String(response.getPayload(), StandardCharsets.UTF_8); System.out.printf("Successfully got shadow %s/%s: %s%n", thingName, shadowName, shadowPayload); } catch (TimeoutException e) { System.err.printf("Timeout occurred while getting shadow: %s/%s%n", thingName, shadowName); } catch (ExecutionException e) { if (e.getCause() instanceof UnauthorizedError) { System.err.printf("Unauthorized error while getting shadow: %s/%s%n", thingName, shadowName); } else if (e.getCause() instanceof ResourceNotFoundError) { System.err.printf("Unable to find shadow to get: %s/%s%n", thingName, shadowName); } else { throw e; } } } catch (InterruptedException e) { System.out.println("IPC interrupted."); } catch (ExecutionException e) { System.err.println("Exception occurred when using IPC."); e.printStackTrace(); System.exit(1); } } public static GetThingShadowResponseHandler getThingShadow(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String shadowName) { GetThingShadowRequest getThingShadowRequest = new GetThingShadowRequest(); getThingShadowRequest.setThingName(thingName); getThingShadowRequest.setShadowName(shadowName); return greengrassCoreIPCClient.getThingShadow(getThingShadowRequest, Optional.empty()); } }
Python (IPC client V1)
例: モノのシャドウを取得する
import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.client as client from awsiot.greengrasscoreipc.model import GetThingShadowRequest TIMEOUT = 10 def sample_get_thing_shadow_request(thingName, shadowName): try: # set up IPC client to connect to the IPC server ipc_client = awsiot.greengrasscoreipc.connect() # create the GetThingShadow request get_thing_shadow_request = GetThingShadowRequest() get_thing_shadow_request.thing_name = thingName get_thing_shadow_request.shadow_name = shadowName # retrieve the GetThingShadow response after sending the request to the IPC server op = ipc_client.new_get_thing_shadow() op.activate(get_thing_shadow_request) fut = op.get_response() result = fut.result(TIMEOUT) return result.payload except InvalidArgumentsError as e: # add error handling ... # except ResourceNotFoundError | UnauthorizedError | ServiceError
JavaScript
例: モノのシャドウを取得する
import { GetThingShadowRequest } from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model'; import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc'; class GetThingShadow { private ipcClient: greengrasscoreipc.Client; private thingName: string; private shadowName: string; constructor() { // Define args parameters here this.thingName = "<define_your_own_thingName>"; this.shadowName = "<define_your_own_shadowName>"; this.bootstrap(); } async bootstrap() { try { this.ipcClient = await getIpcClient(); } catch (err) { // parse the error depending on your use cases throw err } try { await this.handleGetThingShadowOperation(this.thingName, this.shadowName); } catch (err) { // parse the error depending on your use cases throw err } } async handleGetThingShadowOperation( thingName: string, shadowName: string ) { const request: GetThingShadowRequest = { thingName: thingName, shadowName: shadowName }; const response = await this.ipcClient.getThingShadow(request); } } export async function getIpcClient() { try { const ipcClient = greengrasscoreipc.createClient(); await ipcClient.connect() .catch(error => { // parse the error depending on your use cases throw error; }); return ipcClient } catch (err) { // parse the error depending on your use caseså throw err } } const startScript = new GetThingShadow();

UpdateThingShadow

指定したモノのシャドウを更新します。Shadow が存在しない場合は作成されます。

リクエスト

このオペレーションのリクエストには以下のパラメータがあります。

thingName (Python: thing_name)

モノの名前。

タイプ: string

shadowName (Python: shadow_name)

シャドウの名前。モノのクラシックシャドウを指定するには、このパラメータを空の文字列 ("") に設定します。

警告

AWS IoT Greengrass サービスは、AWSManagedGreengrassV2Deployment 名前付きシャドウを使用して、個々のコアデバイスを対象とするデプロイを管理します。この名前付きシャドウは、AWS IoT Greengrass サービスで使用するために予約されています。この名前付きシャドウを更新または削除しないでください。

タイプ: string

payload

BLOB としてのリクエスト状態ドキュメント。

タイプ: 次の情報が含まれる object

state

更新する状態情報。この IPC オペレーションは、指定したフィールドのみに影響します。

このオブジェクトには、次の情報が含まれます。通常、同じリクエストで desired プロパティまたは reported プロパティのいずれかを使用しますが、両方を使用することはありません。

desired

デバイスで更新がリクエストされた state のプロパティと値。

タイプ: キーバリューペアの map

reported

デバイスによってレポートされた state のプロパティと値。

タイプ: キーバリューペアの map

clientToken (Python: client_token)

(オプション) クライアントトークンによってリクエストとレスポンスを対応付けるために使用されるトークン。

タイプ: string

version

(オプション) 更新するローカルシャドウドキュメントのバージョン。シャドウサービスは、指定したバージョンが最新バージョンと一致した場合のみ更新を処理します。

タイプ: integer

レスポンス

このオペレーションのレスポンスには以下の情報が含まれます。

payload

BLOB としてのレスポンス状態ドキュメント。

タイプ: 次の情報が含まれる object

state

状態情報。

このオブジェクトには、次の情報が含まれます。

desired

デバイスで更新がリクエストされた state のプロパティと値。

タイプ: キーバリューペアの map

reported

デバイスによってレポートされた state のプロパティと値。

タイプ: キーバリューペアの map

delta

デバイスによってレポートされた state のプロパティと値。

タイプ: キーバリューペアの map

metadata

いつ状態が更新されたか判別するための、desired および reported セクションの属性ごとのタイムスタンプ。

タイプ: string

timestamp

レスポンスが生成された日付と時刻 (エポック時間)。

タイプ: integer

clientToken (Python: client_token)

リクエストとレスポンスを対応付けるために使用されるトークン。

タイプ: string

version

更新完了後のローカルシャドウドキュメントのバージョン。

タイプ: integer

エラー

このオペレーションは以下のエラーを返す場合があります。

ConflictError

ローカルシャドウサービスで、更新オペレーション中にバージョンの競合が発生しました。これは、リクエストペイロードのバージョンが利用可能な最新のローカルシャドードキュメントのバージョンと一致しない場合に発生します。

InvalidArgumentsError

ローカルシャドウサービスは、リクエストパラメータを検証できません。これは、リクエストに不正な形式の JSON またはサポートされていない文字が含まれている場合に発生する可能性があります。

有効な payload は以下のプロパティを有します。

  • state ノードが存在すること、そして desired または reported の状態情報を含むオブジェクトであること。

  • desired および reported ノードはオブジェクトまたはヌルのいずれかであること。これらのオブジェクトの少なくとも 1 つに有効な状態情報が含まれている必要があります。

  • desired および reported オブジェクトの深さが 8 ノードを超えることはできません。

  • clientToken の値の長さが 64 文字を超えることはできません。

  • version の値は 1 以上である必要があります。

ServiceError

内部サービスエラーが発生したか、IPC サービスへのリクエスト数が、シャドウマネージャーコンポーネントの maxLocalRequestsPerSecondPerThing および maxTotalLocalRequestsRate の設定パラメータで指定された制限を超えました。

UnauthorizedError

コンポーネントの承認ポリシーには、このオペレーションに必要な権限が含まれていません。

以下の例では、カスタムコンポーネントコードでこのオペレーションを呼び出す方法を示します。

Java (IPC client V1)
例: モノのシャドウを更新する
注記

この例は IPCUtils クラスを使用して、AWS IoT Greengrass Core IPC サービスへの接続を作成します。詳細については、「AWS IoT Greengrass Core IPCサービスに接続する」を参照してください。

package com.aws.greengrass.docs.samples.ipc; import com.aws.greengrass.docs.samples.ipc.util.IPCUtils; import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient; import software.amazon.awssdk.aws.greengrass.UpdateThingShadowResponseHandler; import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError; import software.amazon.awssdk.aws.greengrass.model.UpdateThingShadowRequest; import software.amazon.awssdk.aws.greengrass.model.UpdateThingShadowResponse; import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection; import java.nio.charset.StandardCharsets; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class UpdateThingShadow { public static final int TIMEOUT_SECONDS = 10; public static void main(String[] args) { // Use the current core device's name if thing name isn't set. String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0]; String shadowName = args[1]; byte[] shadowPayload = args[2].getBytes(StandardCharsets.UTF_8); try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) { GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection); UpdateThingShadowResponseHandler responseHandler = UpdateThingShadow.updateThingShadow(ipcClient, thingName, shadowName, shadowPayload); CompletableFuture<UpdateThingShadowResponse> futureResponse = responseHandler.getResponse(); try { futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); System.out.printf("Successfully updated shadow: %s/%s%n", thingName, shadowName); } catch (TimeoutException e) { System.err.printf("Timeout occurred while updating shadow: %s/%s%n", thingName, shadowName); } catch (ExecutionException e) { if (e.getCause() instanceof UnauthorizedError) { System.err.printf("Unauthorized error while updating shadow: %s/%s%n", thingName, shadowName); } else { throw e; } } } catch (InterruptedException e) { System.out.println("IPC interrupted."); } catch (ExecutionException e) { System.err.println("Exception occurred when using IPC."); e.printStackTrace(); System.exit(1); } } public static UpdateThingShadowResponseHandler updateThingShadow(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String shadowName, byte[] shadowPayload) { UpdateThingShadowRequest updateThingShadowRequest = new UpdateThingShadowRequest(); updateThingShadowRequest.setThingName(thingName); updateThingShadowRequest.setShadowName(shadowName); updateThingShadowRequest.setPayload(shadowPayload); return greengrassCoreIPCClient.updateThingShadow(updateThingShadowRequest, Optional.empty()); } }
Python (IPC client V1)
例: モノのシャドウを更新する
import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.client as client from awsiot.greengrasscoreipc.model import UpdateThingShadowRequest TIMEOUT = 10 def sample_update_thing_shadow_request(thingName, shadowName, payload): try: # set up IPC client to connect to the IPC server ipc_client = awsiot.greengrasscoreipc.connect() # create the UpdateThingShadow request update_thing_shadow_request = UpdateThingShadowRequest() update_thing_shadow_request.thing_name = thingName update_thing_shadow_request.shadow_name = shadowName update_thing_shadow_request.payload = payload # retrieve the UpdateThingShadow response after sending the request to the IPC server op = ipc_client.new_update_thing_shadow() op.activate(update_thing_shadow_request) fut = op.get_response() result = fut.result(TIMEOUT) return result.payload except InvalidArgumentsError as e: # add error handling ... # except ConflictError | UnauthorizedError | ServiceError
JavaScript
例: モノのシャドウを更新する
import { UpdateThingShadowRequest } from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model'; import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc'; class UpdateThingShadow { private ipcClient: greengrasscoreipc.Client; private thingName: string; private shadowName: string; private shadowDocumentStr: string; constructor() { // Define args parameters here this.thingName = "<define_your_own_thingName>"; this.shadowName = "<define_your_own_shadowName>"; this.shadowDocumentStr = "<define_your_own_payload>"; this.bootstrap(); } async bootstrap() { try { this.ipcClient = await getIpcClient(); } catch (err) { // parse the error depending on your use cases throw err } try { await this.handleUpdateThingShadowOperation( this.thingName, this.shadowName, this.shadowDocumentStr); } catch (err) { // parse the error depending on your use cases throw err } } async handleUpdateThingShadowOperation( thingName: string, shadowName: string, payloadStr: string ) { const request: UpdateThingShadowRequest = { thingName: thingName, shadowName: shadowName, payload: payloadStr } // make the UpdateThingShadow request const response = await this.ipcClient.updateThingShadow(request); } } export async function getIpcClient() { try { const ipcClient = greengrasscoreipc.createClient(); await ipcClient.connect() .catch(error => { // parse the error depending on your use cases throw error; }); return ipcClient } catch (err) { // parse the error depending on your use cases throw err } } const startScript = new UpdateThingShadow();

DeleteThingShadow

指定したモノの Shadow を削除します。

シャドウマネージャー v2.0.4 以降、シャドウを削除するとバージョン番号がインクリメントします。たとえば、バージョン 1 のシャドウ MyThingShadow を削除すると、削除されたシャドウのバージョンは 2 になります。その後 MyThingShadow の名前でシャドウを作成し直すと、そのシャドウのバージョンは 3 になります。

リクエスト

このオペレーションのリクエストには以下のパラメータがあります。

thingName (Python: thing_name)

モノの名前。

タイプ: string

shadowName (Python: shadow_name)

シャドウの名前。モノのクラシックシャドウを指定するには、このパラメータを空の文字列 ("") に設定します。

警告

AWS IoT Greengrass サービスは、AWSManagedGreengrassV2Deployment 名前付きシャドウを使用して、個々のコアデバイスを対象とするデプロイを管理します。この名前付きシャドウは、AWS IoT Greengrass サービスで使用するために予約されています。この名前付きシャドウを更新または削除しないでください。

タイプ: string

レスポンス

このオペレーションのレスポンスには以下の情報が含まれます。

payload

空のレスポンス状態ドキュメント。

エラー

このオペレーションは以下のエラーを返す場合があります。

InvalidArgumentsError

ローカルシャドウサービスは、リクエストパラメータを検証できません。これは、リクエストに不正な形式の JSON またはサポートされていない文字が含まれている場合に発生する可能性があります。

ResourceNotFoundError

要求されたローカルシャドウドキュメントが見つかりません。

ServiceError

内部サービスエラーが発生したか、IPC サービスへのリクエスト数が、シャドウマネージャーコンポーネントの maxLocalRequestsPerSecondPerThing および maxTotalLocalRequestsRate の設定パラメータで指定された制限を超えました。

UnauthorizedError

コンポーネントの承認ポリシーには、このオペレーションに必要な権限が含まれていません。

以下の例では、カスタムコンポーネントコードでこのオペレーションを呼び出す方法を示します。

Java (IPC client V1)
例: モノのシャドウを削除する
注記

この例は IPCUtils クラスを使用して、AWS IoT Greengrass Core IPC サービスへの接続を作成します。詳細については、「AWS IoT Greengrass Core IPCサービスに接続する」を参照してください。

package com.aws.greengrass.docs.samples.ipc; import com.aws.greengrass.docs.samples.ipc.util.IPCUtils; import software.amazon.awssdk.aws.greengrass.DeleteThingShadowResponseHandler; import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient; import software.amazon.awssdk.aws.greengrass.model.DeleteThingShadowRequest; import software.amazon.awssdk.aws.greengrass.model.DeleteThingShadowResponse; import software.amazon.awssdk.aws.greengrass.model.ResourceNotFoundError; import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError; import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class DeleteThingShadow { public static final int TIMEOUT_SECONDS = 10; public static void main(String[] args) { // Use the current core device's name if thing name isn't set. String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0]; String shadowName = args[1]; try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) { GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection); DeleteThingShadowResponseHandler responseHandler = DeleteThingShadow.deleteThingShadow(ipcClient, thingName, shadowName); CompletableFuture<DeleteThingShadowResponse> futureResponse = responseHandler.getResponse(); try { futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); System.out.printf("Successfully deleted shadow: %s/%s%n", thingName, shadowName); } catch (TimeoutException e) { System.err.printf("Timeout occurred while deleting shadow: %s/%s%n", thingName, shadowName); } catch (ExecutionException e) { if (e.getCause() instanceof UnauthorizedError) { System.err.printf("Unauthorized error while deleting shadow: %s/%s%n", thingName, shadowName); } else if (e.getCause() instanceof ResourceNotFoundError) { System.err.printf("Unable to find shadow to delete: %s/%s%n", thingName, shadowName); } else { throw e; } } } catch (InterruptedException e) { System.out.println("IPC interrupted."); } catch (ExecutionException e) { System.err.println("Exception occurred when using IPC."); e.printStackTrace(); System.exit(1); } } public static DeleteThingShadowResponseHandler deleteThingShadow(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String shadowName) { DeleteThingShadowRequest deleteThingShadowRequest = new DeleteThingShadowRequest(); deleteThingShadowRequest.setThingName(thingName); deleteThingShadowRequest.setShadowName(shadowName); return greengrassCoreIPCClient.deleteThingShadow(deleteThingShadowRequest, Optional.empty()); } }
Python (IPC client V1)
例: モノのシャドウを削除する
import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.client as client from awsiot.greengrasscoreipc.model import DeleteThingShadowRequest TIMEOUT = 10 def sample_delete_thing_shadow_request(thingName, shadowName): try: # set up IPC client to connect to the IPC server ipc_client = awsiot.greengrasscoreipc.connect() # create the DeleteThingShadow request delete_thing_shadow_request = DeleteThingShadowRequest() delete_thing_shadow_request.thing_name = thingName delete_thing_shadow_request.shadow_name = shadowName # retrieve the DeleteThingShadow response after sending the request to the IPC server op = ipc_client.new_delete_thing_shadow() op.activate(delete_thing_shadow_request) fut = op.get_response() result = fut.result(TIMEOUT) return result.payload except InvalidArgumentsError as e: # add error handling ... # except ResourceNotFoundError | UnauthorizedError | ServiceError
JavaScript
例: モノのシャドウを削除する
import { DeleteThingShadowRequest } from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model'; import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc'; class DeleteThingShadow { private ipcClient: greengrasscoreipc.Client; private thingName: string; private shadowName: string; constructor() { // Define args parameters here this.thingName = "<define_your_own_thingName>"; this.shadowName = "<define_your_own_shadowName>"; this.bootstrap(); } async bootstrap() { try { this.ipcClient = await getIpcClient(); } catch (err) { // parse the error depending on your use cases throw err } try { await this.handleDeleteThingShadowOperation(this.thingName, this.shadowName) } catch (err) { // parse the error depending on your use cases throw err } } async handleDeleteThingShadowOperation(thingName: string, shadowName: string) { const request: DeleteThingShadowRequest = { thingName: thingName, shadowName: shadowName } // make the DeleteThingShadow request const response = await this.ipcClient.deleteThingShadow(request); } } export async function getIpcClient() { try { const ipcClient = greengrasscoreipc.createClient(); await ipcClient.connect() .catch(error => { // parse the error depending on your use cases throw error; }); return ipcClient } catch (err) { // parse the error depending on your use cases throw err } } const startScript = new DeleteThingShadow();

ListNamedShadowsForThing

指定されたモノの名前付きシャドウを一覧表示します。

リクエスト

このオペレーションのリクエストには以下のパラメータがあります。

thingName (Python: thing_name)

モノの名前。

タイプ: string

pageSize (Python: page_size)

(オプション) 各呼び出しで返すシャドウ名の数。

タイプ: integer

デフォルト: 25

最大: 100

nextToken (Python: next_token)

(オプション) 次の結果セットを取得するためのトークン。この値は、ページングされた結果で返され、次のページを返す呼び出しで使用されます。

タイプ: string

レスポンス

このオペレーションのレスポンスには以下の情報が含まれます。

results

シャドウ名のリスト。

タイプ: array

timestamp

(オプション) レスポンスが生成された日付と時刻。

タイプ: integer

nextToken (Python: next_token)

(オプション) シーケンス内の次のページを取得するためにページングされたリクエストで使用するトークン値。返すシャドウ名がなくなると、このプロパティは存在しません。

タイプ: string

注記

リクエストされたページサイズがレスポンスのシャドウ名の数と完全に一致する場合、このトークンは存在しますが、使用すると空のリストが返されます。

エラー

このオペレーションは以下のエラーを返す場合があります。

InvalidArgumentsError

ローカルシャドウサービスは、リクエストパラメータを検証できません。これは、リクエストに不正な形式の JSON またはサポートされていない文字が含まれている場合に発生する可能性があります。

ResourceNotFoundError

要求されたローカルシャドウドキュメントが見つかりません。

ServiceError

内部サービスエラーが発生したか、IPC サービスへのリクエスト数が、シャドウマネージャーコンポーネントの maxLocalRequestsPerSecondPerThing および maxTotalLocalRequestsRate の設定パラメータで指定された制限を超えました。

UnauthorizedError

コンポーネントの承認ポリシーには、このオペレーションに必要な権限が含まれていません。

以下の例では、カスタムコンポーネントコードでこのオペレーションを呼び出す方法を示します。

Java (IPC client V1)
例:モノの名前付きシャドウを一覧表示
注記

この例は IPCUtils クラスを使用して、AWS IoT Greengrass Core IPC サービスへの接続を作成します。詳細については、「AWS IoT Greengrass Core IPCサービスに接続する」を参照してください。

package com.aws.greengrass.docs.samples.ipc; import com.aws.greengrass.docs.samples.ipc.util.IPCUtils; import software.amazon.awssdk.aws.greengrass.GreengrassCoreIPCClient; import software.amazon.awssdk.aws.greengrass.ListNamedShadowsForThingResponseHandler; import software.amazon.awssdk.aws.greengrass.model.ListNamedShadowsForThingRequest; import software.amazon.awssdk.aws.greengrass.model.ListNamedShadowsForThingResponse; import software.amazon.awssdk.aws.greengrass.model.ResourceNotFoundError; import software.amazon.awssdk.aws.greengrass.model.UnauthorizedError; import software.amazon.awssdk.eventstreamrpc.EventStreamRPCConnection; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class ListNamedShadowsForThing { public static final int TIMEOUT_SECONDS = 10; public static void main(String[] args) { // Use the current core device's name if thing name isn't set. String thingName = args[0].isEmpty() ? System.getenv("AWS_IOT_THING_NAME") : args[0]; try (EventStreamRPCConnection eventStreamRPCConnection = IPCUtils.getEventStreamRpcConnection()) { GreengrassCoreIPCClient ipcClient = new GreengrassCoreIPCClient(eventStreamRPCConnection); List<String> namedShadows = new ArrayList<>(); String nextToken = null; try { // Send additional requests until there's no pagination token in the response. do { ListNamedShadowsForThingResponseHandler responseHandler = ListNamedShadowsForThing.listNamedShadowsForThing(ipcClient, thingName, nextToken, 25); CompletableFuture<ListNamedShadowsForThingResponse> futureResponse = responseHandler.getResponse(); ListNamedShadowsForThingResponse response = futureResponse.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); List<String> responseNamedShadows = response.getResults(); namedShadows.addAll(responseNamedShadows); nextToken = response.getNextToken(); } while (nextToken != null); System.out.printf("Successfully got named shadows for thing %s: %s%n", thingName, String.join(",", namedShadows)); } catch (TimeoutException e) { System.err.println("Timeout occurred while listing named shadows for thing: " + thingName); } catch (ExecutionException e) { if (e.getCause() instanceof UnauthorizedError) { System.err.println("Unauthorized error while listing named shadows for " + "thing: " + thingName); } else if (e.getCause() instanceof ResourceNotFoundError) { System.err.println("Unable to find thing to list named shadows: " + thingName); } else { throw e; } } } catch (InterruptedException e) { System.out.println("IPC interrupted."); } catch (ExecutionException e) { System.err.println("Exception occurred when using IPC."); e.printStackTrace(); System.exit(1); } } public static ListNamedShadowsForThingResponseHandler listNamedShadowsForThing(GreengrassCoreIPCClient greengrassCoreIPCClient, String thingName, String nextToken, int pageSize) { ListNamedShadowsForThingRequest listNamedShadowsForThingRequest = new ListNamedShadowsForThingRequest(); listNamedShadowsForThingRequest.setThingName(thingName); listNamedShadowsForThingRequest.setNextToken(nextToken); listNamedShadowsForThingRequest.setPageSize(pageSize); return greengrassCoreIPCClient.listNamedShadowsForThing(listNamedShadowsForThingRequest, Optional.empty()); } }
Python (IPC client V1)
例:モノの名前付きシャドウを一覧表示
import awsiot.greengrasscoreipc import awsiot.greengrasscoreipc.client as client from awsiot.greengrasscoreipc.model import ListNamedShadowsForThingRequest TIMEOUT = 10 def sample_list_named_shadows_for_thing_request(thingName, nextToken, pageSize): try: # set up IPC client to connect to the IPC server ipc_client = awsiot.greengrasscoreipc.connect() # create the ListNamedShadowsForThingRequest request list_named_shadows_for_thing_request = ListNamedShadowsForThingRequest() list_named_shadows_for_thing_request.thing_name = thingName list_named_shadows_for_thing_request.next_token = nextToken list_named_shadows_for_thing_request.page_size = pageSize # retrieve the ListNamedShadowsForThingRequest response after sending the request to the IPC server op = ipc_client.new_list_named_shadows_for_thing() op.activate(list_named_shadows_for_thing_request) fut = op.get_response() list_result = fut.result(TIMEOUT) # additional returned fields timestamp = list_result.timestamp next_token = result.next_token named_shadow_list = list_result.results return named_shadow_list, next_token, timestamp except InvalidArgumentsError as e: # add error handling ... # except ResourceNotFoundError | UnauthorizedError | ServiceError
JavaScript
例:モノの名前付きシャドウを一覧表示
import { ListNamedShadowsForThingRequest } from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc/model'; import * as greengrasscoreipc from 'aws-iot-device-sdk-v2/dist/greengrasscoreipc'; class listNamedShadowsForThing { private ipcClient: greengrasscoreipc.Client; private thingName: string; private pageSizeStr: string; private nextToken: string; constructor() { // Define args parameters here this.thingName = "<define_your_own_thingName>"; this.pageSizeStr = "<define_your_own_pageSize>"; this.nextToken = "<define_your_own_token>"; this.bootstrap(); } async bootstrap() { try { this.ipcClient = await getIpcClient(); } catch (err) { // parse the error depending on your use cases throw err } try { await this.handleListNamedShadowsForThingOperation(this.thingName, this.nextToken, this.pageSizeStr); } catch (err) { // parse the error depending on your use cases throw err } } async handleListNamedShadowsForThingOperation( thingName: string, nextToken: string, pageSizeStr: string ) { let request: ListNamedShadowsForThingRequest = { thingName: thingName, nextToken: nextToken, }; if (pageSizeStr) { request.pageSize = parseInt(pageSizeStr); } // make the ListNamedShadowsForThing request const response = await this.ipcClient.listNamedShadowsForThing(request); const shadowNames = response.results; } } export async function getIpcClient(){ try { const ipcClient = greengrasscoreipc.createClient(); await ipcClient.connect() .catch(error => { // parse the error depending on your use cases throw error; }); return ipcClient } catch (err) { // parse the error depending on your use cases throw err } } const startScript = new listNamedShadowsForThing();