

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 與本機陰影互動
<a name="ipc-local-shadows"></a>

使用影子 IPC 服務與裝置上的本機影子互動。您選擇與之互動的裝置可以是您的核心裝置或連線的用戶端裝置。

若要使用這些 IPC 操作，請在自訂[元件中包含影子管理員](shadow-manager-component.md)元件做為相依性。然後，您可以在自訂元件中使用 IPC 操作，透過影子管理員與裝置上的本機影子互動。若要讓自訂元件對本機影子狀態的變更做出反應，您也可以使用發佈/訂閱 IPC 服務來訂閱影子事件。如需使用發佈/訂閱服務的詳細資訊，請參閱 [發佈/訂閱本機訊息](ipc-publish-subscribe.md)。

**注意**  <a name="note-requirement-enable-shadow-manager-client-devices"></a>
若要讓核心裝置與用戶端裝置影子互動，您還必須設定和部署 MQTT 橋接器元件。如需詳細資訊，請參閱[啟用影子管理員以與用戶端裝置通訊](work-with-client-device-shadows.md)。

**Topics**
+ [最低 SDK 版本](#ipc-local-shadows-sdk-versions)
+ [Authorization](#ipc-local-shadow-authorization)
+ [GetThingShadow](#ipc-operation-getthingshadow)
+ [UpdateThingShadow](#ipc-operation-updatethingshadow)
+ [DeleteThingShadow](#ipc-operation-deletethingshadow)
+ [ListNamedShadowsForThing](#ipc-operation-listnamedshadowsforthing)

## 最低 SDK 版本
<a name="ipc-local-shadows-sdk-versions"></a>

下表列出您可以用來與本機影子互動SDKs最低版本。


| SDK | 最低版本 | 
| --- | --- | 
|  [AWS IoT Greengrass 元件 SDK (C、C\$1\$1、Rust)](https://github.com/aws-greengrass/aws-greengrass-component-sdk)  |  v1.0.0  | 
|  [AWS IoT Device SDK for Java v2](https://github.com/aws/aws-iot-device-sdk-java-v2)  |  1.4.0 版  | 
|  [AWS IoT Device SDK for Python v2](https://github.com/aws/aws-iot-device-sdk-python-v2)  |  v1.6.0  | 
|  [AWS IoT Device SDK 適用於 C\$1\$1 v2](https://github.com/aws/aws-iot-device-sdk-cpp-v2)  |  1.17.0 版  | 
|  [AWS IoT Device SDK for JavaScript v2](https://github.com/aws/aws-iot-device-sdk-js-v2)  |  v1.12.0  | 

## Authorization
<a name="ipc-local-shadow-authorization"></a>

若要在自訂元件中使用陰影 IPC 服務，您必須定義授權政策，允許您的元件與陰影互動。如需定義授權政策的資訊，請參閱 [授權元件執行 IPC 操作](interprocess-communication.md#ipc-authorization-policies)。

陰影互動的授權政策具有下列屬性。

**IPC 服務識別符：** `aws.greengrass.ShadowManager`


| 作業 | Description | Resources | 
| --- | --- | --- | 
|  `aws.greengrass#GetThingShadow`  |  允許元件擷取物件的陰影。  |  下列其中一個字串： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/greengrass/v2/developerguide/ipc-local-shadows.html)  | 
|  `aws.greengrass#UpdateThingShadow`  |  允許元件更新物件的陰影。  |  下列其中一個字串： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/greengrass/v2/developerguide/ipc-local-shadows.html)  | 
|  `aws.greengrass#DeleteThingShadow`  |  允許元件刪除物件的陰影。  |  下列其中一個字串： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/greengrass/v2/developerguide/ipc-local-shadows.html)  | 
|  `aws.greengrass#ListNamedShadowsForThing`  |  允許元件擷取物件的具名影子清單。  |  物件名稱字串，允許存取物件以列出其影子。 使用 `*` 允許存取所有物件。  | 

**IPC 服務識別符：** `aws.greengrass.ipc.pubsub`


| 作業 | Description | Resources | 
| --- | --- | --- | 
|  `aws.greengrass#SubscribeToTopic`  |  允許元件訂閱您指定主題的訊息。  |  下列其中一個主題字串： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/greengrass/v2/developerguide/ipc-local-shadows.html) 主題字首的值`shadowTopicPrefix`取決於影子的類型： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/greengrass/v2/developerguide/ipc-local-shadows.html) 使用 `*` 允許存取所有主題。 <a name="ipc-local-publish-subscribe-authorization-mqtt-wildcards"></a>在 [Greengrass 核](greengrass-nucleus-component.md) v2.6.0 和更新版本中，您可以訂閱包含 MQTT 主題萬用字元 (`#` 和 `+`) 的主題。此主題字串支援 MQTT 主題萬用字元做為文字字元。例如，如果元件的授權政策授予 的存取權`test/topic/#`，則該元件可以訂閱 `test/topic/#`，但無法訂閱 `test/topic/filter`。  | 

### 本機影子授權政策中的配方變數
<a name="ipc-local-shadow-authorization-recipe-variables"></a>

如果您使用 [Greengrass 核](greengrass-nucleus-component.md)的 v2.6.0 或更新版本，並將 Greengrass 核的 [interpolateComponentConfiguration](greengrass-nucleus-component.md#greengrass-nucleus-component-configuration-interpolate-component-configuration) 組態選項設定為 `true`，您可以在授權政策中使用`{iot:thingName}`[配方變數](component-recipe-reference.md#recipe-variables)。此功能可讓您為一組核心裝置設定單一授權政策，其中每個核心裝置只能存取自己的影子。例如，您可以允許元件存取陰影 IPC 操作的下列資源。

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

### 授權政策範例
<a name="ipc-local-shadow-authorization-policy-examples"></a>

您可以參考下列授權政策範例，協助您設定元件的授權政策。

**Example 範例：允許一組核心裝置與本機影子互動**  
 <a name="phrase-example-uses-recipe-variables-in-configuration"></a>此範例使用適用於 [Greengrass 核元件](greengrass-nucleus-component.md) v2.6.0 和更新版本的功能。Greengrass 核 v2.6.0 新增對元件組態中大多數[配方變數](component-recipe-reference.md#recipe-variables)的支援`{iot:thingName}`，例如 。若要啟用此功能，請將 Greengrass 核的 [interpolateComponentConfiguration](greengrass-nucleus-component.md#greengrass-nucleus-component-configuration-interpolate-component-configuration) 組態選項設定為 `true`。如需適用於所有 Greengrass 核版本的範例，請參閱[單一核心裝置的範例授權政策](#ipc-local-shadows-authorization-example-single-device)。
下列範例授權政策允許 元件與傳統裝置影子和執行元件`myNamedShadow`之核心裝置的具名影子`com.example.MyShadowInteractionComponent`互動。此政策也允許此元件接收有關這些影子之本機主題的訊息。  

```
{
  "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"
        ]
      }
    }
  }
}
```

```
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
```

**Example 範例：允許一組核心裝置與用戶端裝置影子互動**  
此功能需要 [Greengrass 核](greengrass-nucleus-component.md) v2.6.0 或更新版本、[陰影管理員](shadow-manager-component.md) v2.2.0 或更新版本，以及 [MQTT 橋接](mqtt-bridge-component.md)器 v2.2.0 或更新版本。您必須設定 MQTT 橋接器，[讓陰影管理員能夠與用戶端裝置通訊](work-with-client-device-shadows.md#enable-shadow-manager-client-devices)。
下列範例授權政策允許 元件與名稱開頭為 的用戶端裝置的所有裝置影子`com.example.MyShadowInteractionComponent`互動`MyClientDevice`。  
若要讓核心裝置與用戶端裝置影子互動，您還必須設定和部署 MQTT 橋接器元件。如需詳細資訊，請參閱[啟用影子管理員以與用戶端裝置通訊](work-with-client-device-shadows.md)。

```
{
  "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*"
        ]
      }    
    }
  }
}
```

```
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*
```<a name="ipc-local-shadows-authorization-example-single-device"></a>

**Example 範例：允許單一核心裝置與本機影子互動**  
下列範例授權政策允許 元件與傳統裝置影子 和裝置 `myNamedShadow` 的具名影子 `com.example.MyShadowInteractionComponent`互動`MyThingName`。此政策也允許此元件接收有關這些影子之本機主題的訊息。  

```
{
  "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"
        ]
      }
    }
  }
}
```

```
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
```<a name="interact-with-shadows-react-example-authorization-policies"></a>

**Example 範例：允許一組核心裝置對本機陰影狀態變更做出反應**  
 <a name="phrase-example-uses-recipe-variables-in-configuration"></a>此範例使用適用於 [Greengrass 核元件](greengrass-nucleus-component.md) v2.6.0 和更新版本的功能。Greengrass 核 v2.6.0 在元件組態中新增了對大多數[配方變數](component-recipe-reference.md#recipe-variables)的支援`{iot:thingName}`，例如 。若要啟用此功能，請將 Greengrass 核的 [interpolateComponentConfiguration](greengrass-nucleus-component.md#greengrass-nucleus-component-configuration-interpolate-component-configuration) 組態選項設定為 `true`。如需適用於所有 Greengrass 核版本的範例，請參閱[單一核心裝置的範例授權政策](#interact-with-shadows-react-example-authorization-policy-single-device)。
下列範例存取控制政策允許自訂`com.example.MyShadowReactiveComponent`接收傳統裝置影子`/update/delta`主題的訊息，以及`myNamedShadow`每個核心裝置上執行元件的具名影子。  

```
{
  "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"
        ]
      }
    }
  }
}
```

```
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
```<a name="interact-with-shadows-react-example-authorization-policy-single-device"></a>

**Example 範例：允許單一核心裝置對本機陰影狀態變更做出反應**  
下列範例存取控制政策允許自訂`com.example.MyShadowReactiveComponent`接收傳統裝置影子`/update/delta`主題和裝置 `myNamedShadow`具名影子的訊息`MyThingName`。  

```
{
  "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"
        ]
      }
    }
  }
}
```

```
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
<a name="ipc-operation-getthingshadow"></a>

取得指定物件的陰影。

### 請求
<a name="ipc-operation-getthingshadow-request"></a>

此操作的請求具有下列參數：

`thingName` (Python：`thing_name`)  <a name="ipc-local-shadows-thing-name"></a>
物件名稱。  
類型：`string`

`shadowName` (Python：`shadow_name`)  <a name="ipc-local-shadows-shadow-name"></a>
影子的名稱。若要指定物件的傳統陰影，請將此參數設定為空字串 (`""`)。  
 AWS IoT Greengrass 服務使用`AWSManagedGreengrassV2Deployment`具名影子來管理以個別核心裝置為目標的部署。此具名影子會保留供 AWS IoT Greengrass 服務使用。請勿更新或刪除此具名影子。
類型：`string`

### 回應
<a name="ipc-operation-getthingshadow-response"></a>

此操作的回應包含下列資訊：

`payload`  
Blob 形式的回應狀態文件。  
類型：`object`包含下列資訊：    
`state`  
狀態資訊。  
此物件包含下列資訊。    
`desired`  
在裝置中請求更新的狀態屬性和值。  
類型：`map`鍵/值對  
`reported`  
裝置報告的狀態屬性和值。  
類型：`map`鍵/值對  
`delta`  
所需和報告的狀態屬性和值之間的差異。只有在 `desired`和 `reported` 狀態不同時，才會顯示此屬性。  
類型：鍵值對`map`的  
`metadata`  
`desired` 和 `reported`區段中每個屬性的時間戳記，讓您可以判斷狀態的更新時間。  
類型：`string`  
`timestamp`  
產生回應的 epoch 日期和時間。  
類型：`integer`  
`clientToken` (Python：`clientToken`)  
用於比對請求和對應回應的字符  
類型：`string`  
`version`  
本機影子文件的版本。  
類型：`integer`

### 錯誤
<a name="ipc-operation-getthingshadow-errors"></a>

此操作可能會傳回下列錯誤。

`InvalidArgumentsError`  <a name="ipc-invalidargumentserror"></a>
<a name="ipc-invalidargumentserror-para"></a>本機影子服務無法驗證請求參數。如果請求包含格式不正確的 JSON 或不支援的字元，就會發生這種情況。

`ResourceNotFoundError`  <a name="ipc-resourcenotfounderror"></a>
找不到請求的本機影子文件。

`ServiceError`  <a name="ipc-serviceerror"></a>
發生內部服務錯誤，或對 IPC 服務的請求數量超過影子管理員元件中 `maxLocalRequestsPerSecondPerThing`和 `maxTotalLocalRequestsRate`組態參數中指定的限制。

`UnauthorizedError`  <a name="ipc-unauthorizederror"></a>
元件的授權政策不包含此操作所需的許可。

### 範例
<a name="ipc-operation-getthingshadow-examples"></a>

下列範例示範如何在自訂元件程式碼中呼叫此操作。

------
#### [ Java (IPC client V1) ]

**Example 範例：取得物件影子**  
此範例使用 `IPCUtils`類別來建立與 AWS IoT Greengrass Core IPC 服務的連線。如需詳細資訊，請參閱[連線至 AWS IoT Greengrass Core IPC 服務](interprocess-communication.md#ipc-service-connect)。

```
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) ]

**Example 範例：取得物件影子**  

```
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 ]

**Example 範例：取得物件影子**  

```
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
<a name="ipc-operation-updatethingshadow"></a>

更新指定物件的影子。如果影子不存在，則會建立一個影子。

### 請求
<a name="ipc-operation-updatethingshadow-request"></a>

此操作的請求具有下列參數：

`thingName` (Python：`thing_name`)  <a name="ipc-local-shadows-thing-name"></a>
物件名稱。  
類型：`string`

`shadowName` (Python：`shadow_name`)  <a name="ipc-local-shadows-shadow-name"></a>
影子的名稱。若要指定物件的傳統陰影，請將此參數設定為空字串 (`""`)。  
 AWS IoT Greengrass 服務使用`AWSManagedGreengrassV2Deployment`具名影子來管理以個別核心裝置為目標的部署。此具名影子會保留供 AWS IoT Greengrass 服務使用。請勿更新或刪除此具名影子。
類型：`string`

`payload`  
請求狀態文件做為 Blob。  
類型：`object`包含下列資訊：    
`state`  
要更新的狀態資訊。此 IPC 操作只會影響指定的欄位。  
此物件包含下列資訊。一般而言，您會使用 `desired` 屬性或 `reported` 屬性，但在相同的請求中不會同時使用兩者。    
`desired`  
在裝置中請求更新的狀態屬性和值。  
類型：鍵值對`map`的  
`reported`  
裝置報告的狀態屬性和值。  
類型：鍵值對`map`的  
`clientToken` (Python：`client_token`)  
（選用） 用於比對請求的字符，以及用戶端字符對應的回應。  
類型：`string`  
`version`  
（選用） 要更新的本機影子文件版本。只有當指定的版本符合其擁有的最新版本時，陰影服務才會處理更新。  
類型：`integer`

### 回應
<a name="ipc-operation-updatethingshadow-response"></a>

此操作的回應包含下列資訊：

`payload`  
Blob 形式的回應狀態文件。  
類型：`object`包含下列資訊：    
`state`  
狀態資訊。  
此物件包含下列資訊。    
`desired`  
在裝置中請求更新的狀態屬性和值。  
類型：鍵值對`map`的  
`reported`  
裝置報告的狀態屬性和值。  
類型：鍵值對`map`的  
`delta`  
裝置報告的狀態屬性和值。  
類型：鍵值對`map`的  
`metadata`  
`desired` 和 `reported`區段中每個屬性的時間戳記，讓您可以判斷狀態的更新時間。  
類型：`string`  
`timestamp`  
產生回應的 epoch 日期和時間。  
類型：`integer`  
`clientToken` (Python：`client_token`)  
用於比對請求和對應回應的字符。  
類型：`string`  
`version`  
更新完成後的本機影子文件版本。  
類型：`integer`

### 錯誤
<a name="ipc-operation-updatethingshadow-errors"></a>

此操作可能會傳回下列錯誤。

`ConflictError`  
本機影子服務在更新操作期間遇到版本衝突。當請求承載中的版本與最新可用本機影子文件中的版本不相符時，就會發生這種情況。

`InvalidArgumentsError`  
<a name="ipc-invalidargumentserror-para"></a>本機影子服務無法驗證請求參數。如果請求包含格式不正確的 JSON 或不支援的字元，就會發生這種情況。  
有效的 `payload`具有下列屬性：  
+ `state` 節點存在，且 是包含 `desired`或 `reported` 狀態資訊的物件。
+ `desired` 和 `reported`節點是物件或 null。其中至少有一個物件必須包含有效的狀態資訊。
+ `desired` 和 `reported` 物件的深度不能超過八個節點。
+ `clientToken` 值的長度不能超過 64 個字元。
+  `version` 值必須為 `1` 或更高。

`ServiceError`  <a name="ipc-serviceerror"></a>
發生內部服務錯誤，或對 IPC 服務的請求數量超過影子管理員元件中 `maxLocalRequestsPerSecondPerThing`和 `maxTotalLocalRequestsRate`組態參數中指定的限制。

`UnauthorizedError`  <a name="ipc-unauthorizederror"></a>
元件的授權政策不包含此操作所需的許可。

### 範例
<a name="ipc-operation-updatethingshadow-examples"></a>

下列範例示範如何在自訂元件程式碼中呼叫此操作。

------
#### [ Java (IPC client V1) ]

**Example 範例：更新物件影子**  
此範例使用 `IPCUtils`類別來建立與 AWS IoT Greengrass Core IPC 服務的連線。如需詳細資訊，請參閱[連線至 AWS IoT Greengrass Core IPC 服務](interprocess-communication.md#ipc-service-connect)。

```
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) ]

**Example 範例：更新物件影子**  

```
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 ]

**Example 範例：更新物件影子**  

```
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
<a name="ipc-operation-deletethingshadow"></a>

刪除特定物件的影子。

從影子管理員 v2.0.4 開始，刪除影子會增加版本編號。例如，當您刪除`MyThingShadow`第 1 版的影子時，已刪除影子的版本為 2。如果您接著重新建立名稱為 的影子`MyThingShadow`，則該影子的版本為 3。

### 請求
<a name="ipc-operation-deletethingshadow-request"></a>

此操作的請求具有下列參數：

`thingName` (Python：`thing_name`)  <a name="ipc-local-shadows-thing-name"></a>
物件名稱。  
類型：`string`

`shadowName` (Python：`shadow_name`)  <a name="ipc-local-shadows-shadow-name"></a>
影子的名稱。若要指定物件的傳統陰影，請將此參數設定為空字串 (`""`)。  
 AWS IoT Greengrass 服務使用`AWSManagedGreengrassV2Deployment`具名影子來管理以個別核心裝置為目標的部署。此具名影子會保留供 AWS IoT Greengrass 服務使用。請勿更新或刪除此具名影子。
類型：`string`

### 回應
<a name="ipc-operation-deletethingshadow-response"></a>

此操作的回應包含下列資訊：

`payload`  
空的回應狀態文件。

### 錯誤
<a name="ipc-operation-deletethingshadow-errors"></a>

此操作可能會傳回下列錯誤。

`InvalidArgumentsError`  <a name="ipc-invalidargumentserror"></a>
<a name="ipc-invalidargumentserror-para"></a>本機影子服務無法驗證請求參數。如果請求包含格式不正確的 JSON 或不支援的字元，就會發生這種情況。

`ResourceNotFoundError`  <a name="ipc-resourcenotfounderror"></a>
找不到請求的本機影子文件。

`ServiceError`  <a name="ipc-serviceerror"></a>
發生內部服務錯誤，或對 IPC 服務的請求數量超過影子管理員元件中 `maxLocalRequestsPerSecondPerThing`和 `maxTotalLocalRequestsRate`組態參數中指定的限制。

`UnauthorizedError`  <a name="ipc-unauthorizederror"></a>
元件的授權政策不包含此操作所需的許可。

### 範例
<a name="ipc-operation-deletethingshadow-examples"></a>

下列範例示範如何在自訂元件程式碼中呼叫此操作。

------
#### [ Java (IPC client V1) ]

**Example 範例：刪除物件影子**  
此範例使用 `IPCUtils`類別來建立與 AWS IoT Greengrass Core IPC 服務的連線。如需詳細資訊，請參閱[連線至 AWS IoT Greengrass Core IPC 服務](interprocess-communication.md#ipc-service-connect)。

```
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) ]

**Example 範例：刪除物件影子**  

```
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 ]

**Example 範例：刪除物件影子**  

```
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
<a name="ipc-operation-listnamedshadowsforthing"></a>

列出指定物件的具名影子。

### 請求
<a name="ipc-operation-listnamedshadowsforthing-request"></a>

此操作的請求具有下列參數：

`thingName` (Python：`thing_name`)  <a name="ipc-local-shadows-thing-name"></a>
物件名稱。  
類型：`string`

`pageSize` (Python：`page_size`)  
（選用） 每次呼叫中要傳回的陰影名稱數量。  
類型：`integer`  
預設：25  
上限：100

`nextToken` (Python：`next_token`)  
（選用） 擷取下一組結果的字符。此值會在分頁結果上傳回，並在傳回下一頁的呼叫中使用。  
類型：`string`

### 回應
<a name="ipc-operation-listnamedshadowsforthing-response"></a>

此操作的回應包含下列資訊：

`results`  
陰影名稱的清單。  
類型：`array`

`timestamp`  
（選用） 產生回應的日期和時間。  
類型：`integer`

`nextToken` (Python：`next_token`)  
（選用） 在分頁請求中使用的字符值，用於擷取序列中的下一頁。當不再傳回陰影名稱時，此字符不存在。  
類型：`string`  
如果請求的頁面大小完全符合回應中的陰影名稱數量，則此字符存在；但是，使用時，它會傳回空清單。

### 錯誤
<a name="ipc-operation-listnamedshadowsforthing-errors"></a>

此操作可能會傳回下列錯誤。

`InvalidArgumentsError`  <a name="ipc-invalidargumentserror"></a>
<a name="ipc-invalidargumentserror-para"></a>本機影子服務無法驗證請求參數。如果請求包含格式不正確的 JSON 或不支援的字元，就會發生這種情況。

`ResourceNotFoundError`  <a name="ipc-resourcenotfounderror"></a>
找不到請求的本機影子文件。

`ServiceError`  <a name="ipc-serviceerror"></a>
發生內部服務錯誤，或對 IPC 服務的請求數量超過影子管理員元件中 `maxLocalRequestsPerSecondPerThing`和 `maxTotalLocalRequestsRate`組態參數中指定的限制。

`UnauthorizedError`  <a name="ipc-unauthorizederror"></a>
元件的授權政策不包含此操作所需的許可。

### 範例
<a name="ipc-operation-listnamedshadowsforthing-examples"></a>

下列範例示範如何在自訂元件程式碼中呼叫此操作。

------
#### [ Java (IPC client V1) ]

**Example 範例：列出物件的命名影子**  
此範例使用 `IPCUtils`類別來建立與 AWS IoT Greengrass Core IPC 服務的連線。如需詳細資訊，請參閱[連線至 AWS IoT Greengrass Core IPC 服務](interprocess-communication.md#ipc-service-connect)。

```
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) ]

**Example 範例：列出物件的命名影子**  

```
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 ]

**Example 範例：列出物件的命名影子**  

```
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();
```

------