

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

# 與影子互動
<a name="device-shadow-data-flow"></a>

本主題說明與 AWS IoT 提供使用影子的三種方法中的每一種相關聯的訊息。這些方法包括下列各項：

`UPDATE`  <a name="update"></a>
建立一個影子，如果它不存在，或者使用訊息正文中提供的狀態訊息更新現有影子的內容。 AWS IoT 會記錄每次更新的時間戳記，以指出上次更新狀態的時間。當影子的狀態變更時， 會 AWS IoT 傳送訊息`/delta`給所有 MQTT 訂閱者，並顯示 `desired`與 `reported` 狀態之間的差異。接收 `/delta` 訊息的裝置或應用程式會根據差異執行動作。例如，裝置可以更新其狀態至所需的狀態，或者應用程式可以更新 UI 以反映裝置狀態的改變。

`GET`  <a name="get"></a>
擷取包含影子完整狀態的目前影子文件，包括中繼資料。

`DELETE`  <a name="delete"></a>
刪除裝置影子及其內容。  
您無法還原已刪除的裝置影子文件，但可以使用已刪除的裝置影子文件的名稱建立新的裝置影子。如果您建立的裝置影子文件名稱與過去 48 小時內刪除的文件名稱相同，則新裝置影子文件的版本號碼會跟隨已刪除影子的版本號碼。如果裝置影子文件已刪除超過 48 小時，則使用相同名稱的新裝置影子文件的版本號碼將會是 0。

## 通訊協定支援
<a name="protocol-support"></a>

AWS IoT 透過 HTTPS 通訊協定支援 [MQTT](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html) 和 REST API 來與影子互動。 為 MQTT 發佈和訂閱動作 AWS IoT 提供一組預留請求和回應主題。裝置和應用程式應先訂閱回應主題，再發佈至請求主題，以取得 AWS IoT 如何處理請求的資訊。如需詳細資訊，請參閱[Device Shadow MQTT 主題](device-shadow-mqtt.md)及[Device Shadow REST API](device-shadow-rest-api.md)。

## 請求和報告狀態
<a name="shadow-reporting-state"></a>

使用 AWS IoT 和影子設計 IoT 解決方案時，您應該判斷將請求變更的應用程式或裝置，以及將實作變更的應用程式或裝置。一般而言，裝置會實作並報告變更回影子，而應用程式和服務會回應並請求影子中的變更。您的解決方案可能不同，但本主題中的範例假設用戶端應用程式或服務請求變更影子中，而裝置會執行變更，並將它們回報給影子。

## 更新影子
<a name="update-device-shadow"></a>

您的應用程式或服務可以使用 [UpdateThingShadow](device-shadow-rest-api.md#API_UpdateThingShadow) API 或發佈至 [/update](device-shadow-mqtt.md#update-pub-sub-topic) 主題來更新影子的狀態。更新只會影響請求中所指定的欄位。

### 當用戶端請求狀態變更時更新影子
<a name="update-pub-sub-topic-client"></a>

**當用戶端使用 MQTT 通訊協定請求影子中的狀態變更**

1. 用戶端應具有目前的影子文件，以便識別要變更的屬性。請參閱 /get 動作，了解如何取得目前的影子文件。

1. 用戶端會訂閱下列 MQTT 主題：
   + `$aws/things/thingName/shadow/name/shadowName/update/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/update/rejected`
   + `$aws/things/thingName/shadow/name/shadowName/update/delta`
   + `$aws/things/thingName/shadow/name/shadowName/update/documents`

1. 用戶端會發佈 `$aws/things/thingName/shadow/name/shadowName/update` 請求主題，其中包含所需的影子狀態的狀態文件。只有要變更的屬性需要包含在文件中。這是具有所需狀態的文件的範例。

   ```
   {
     "state": {
       "desired": {
         "color": {
           "r": 10
         },
         "engine": "ON"
       }
     }
   }
   ```

1. 如果更新請求有效， 會在影子中 AWS IoT 更新所需的狀態，並在這些主題上發佈訊息：
   + `$aws/things/thingName/shadow/name/shadowName/update/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/update/delta`

   `/update/accepted` 訊息包含 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted) 影子文件，而 `/update/delta` 訊息包含 [/delta response state document](device-shadow-document.md#device-shadow-example-response-json-delta) 影子文件。

1. 如果更新請求無效， 會使用描述錯誤的[錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)影子文件 AWS IoT 發佈具有 `$aws/things/thingName/shadow/name/shadowName/update/rejected`主題的訊息。

**當用戶端請求在影子中使用 API 的狀態變更**

1. 用戶端呼叫 `UpdateThingShadow` API，包含作為其訊息內文的 [請求狀態文件](device-shadow-document.md#device-shadow-example-request-json) 狀態文件。

1. 如果請求有效， 會 AWS IoT 傳回 HTTP 成功回應碼和[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)影子文件作為其回應訊息內文。

   AWS IoT 也會發佈 MQTT 訊息至 `$aws/things/thingName/shadow/name/shadowName/update/delta`主題，其中包含訂閱該訊息的任何裝置或用戶端的[/delta response state document](device-shadow-document.md#device-shadow-example-response-json-delta)影子文件。

1. 如果請求無效， 會 AWS IoT 傳回 HTTP 錯誤回應代碼 [錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)作為其回應訊息內文。

當裝置收到有關 `/update/delta` 主題的 `/desired` 狀態時，它會在裝置中進行所需的變更。然後，它會將訊息傳送至 `/update` 主題，向影子報告其目前狀態。

### 當裝置回報其目前狀態時更新影子
<a name="update-pub-sub-topic-device"></a>

**當裝置使用 MQTT 通訊協定向影子報告其目前的狀態**

1. 裝置應該在更新影子之前訂閱這些 MQTT 主題：
   + `$aws/things/thingName/shadow/name/shadowName/update/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/update/rejected`
   + `$aws/things/thingName/shadow/name/shadowName/update/delta`
   + `$aws/things/thingName/shadow/name/shadowName/update/documents`

1. 裝置會將訊息發佈至報告目前狀態的 `$aws/things/thingName/shadow/name/shadowName/update` 主題，例如在此範例中，以報告其目前狀態。

   ```
   {
       "state": {
           "reported" : {
               "color" : { "r" : 10 },
               "engine" : "ON"
           }
       }
   }
   ```

1. 如果 AWS IoT 接受更新，它會發佈訊息到具有[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)影子文件`$aws/things/thingName/shadow/name/shadowName/update/accepted`的主題。

1. 如果更新請求無效， 會使用描述錯誤的[錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)影子文件 AWS IoT 發佈具有 `$aws/things/thingName/shadow/name/shadowName/update/rejected`主題的訊息。

**當裝置藉由使用 API 向影子報告其目前的狀態**

1. 裝置會呼叫 `UpdateThingShadow` API，包含 [請求狀態文件](device-shadow-document.md#device-shadow-example-request-json) 狀態文件作為其訊息正文。

1. 如果請求有效， 會 AWS IoT 更新影子，並傳回 HTTP 成功回應碼，其中包含影[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)子文件作為其回應訊息內文。

   AWS IoT 也會發佈 MQTT 訊息至 `$aws/things/thingName/shadow/name/shadowName/update/delta`主題，其中包含訂閱該訊息的任何裝置或用戶端的[/delta response state document](device-shadow-document.md#device-shadow-example-response-json-delta)影子文件。

1. 如果請求無效， 會 AWS IoT 傳回 HTTP 錯誤回應代碼 [錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)作為其回應訊息內文。

### 樂觀鎖定
<a name="optimistic-locking"></a>

您可以使用狀態文件版本，確認您正在更新的裝置影子文件為最新版本。當您為更新請求提供版本，若狀態文件的目前版本與提供的版本不符，則服務會拒絕請求並顯示 HTTP 409 衝突回應代碼。衝突回應代碼也會出現在任何修改 `ThingShadow` 的 API 上，包括 `DeleteThingShadow`。

例如：

初始文件：

```
{
  "state": {
    "desired": {
      "colors": [
        "RED",
        "GREEN",
        "BLUE"
      ]
    }
  },
  "version": 10
}
```

更新：(版本不符合；系統將拒絕請求)

```
{
  "state": {
    "desired": {
      "colors": [
        "BLUE"
      ]
    }
  },
  "version": 9
}
```

結果：

```
{
  "code": 409,
  "message": "Version conflict",
  "clientToken": "426bfd96-e720-46d3-95cd-014e3ef12bb6"
}
```

更新：(版本符合；將接受請求)

```
{
  "state": {
    "desired": {
      "colors": [
        "BLUE"
      ]
    }
  },
  "version": 10
}
```

最終狀態：

```
{
  "state": {
    "desired": {
      "colors": [
        "BLUE"
      ]
    }
  },
  "version": 11
}
```

## 擷取影子文件
<a name="retrieving-device-shadow"></a>

您可以使用 [GetThingShadow](device-shadow-rest-api.md#API_GetThingShadow) API 或訂閱並發行至 [/get](device-shadow-mqtt.md#get-pub-sub-topic) 主題來擷取影子文件。這會擷取完整的影子文件，包括 `desired` 和 `reported` 狀態之間的任何差異。無論裝置或用戶端正在提出請求，此工作的程序都是相同的。

**使用 MQTT 通訊協定擷取影子文件**

1. 裝置或用戶端應該在更新影子之前訂閱這些 MQTT 主題：
   + `$aws/things/thingName/shadow/name/shadowName/get/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/get/rejected`

1. 裝置或用戶端會將訊息發佈至具有空白訊息內文的 `$aws/things/thingName/shadow/name/shadowName/get` 主題。

1. 如果請求成功， 會在訊息內文[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)中使用 AWS IoT 發佈訊息至`$aws/things/thingName/shadow/name/shadowName/get/accepted`主題。

1. 如果請求無效， 會將訊息 AWS IoT 發佈至訊息內文[錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)中具有 的 `$aws/things/thingName/shadow/name/shadowName/get/rejected`主題。

**使用 REST API 擷取影子文件**

1. 裝置或用戶端會使用空的訊息內文呼叫 `GetThingShadow` API。

1. 如果請求有效， 會 AWS IoT 傳回 HTTP 成功回應程式碼，並將[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)影子文件作為回應訊息內文。

1. 如果請求無效， 會 AWS IoT 傳回 HTTP 錯誤回應代碼 [錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)作為其回應訊息內文。

## 刪除影子資料
<a name="deleting-thing-data"></a>

有兩種方法可以刪除影子資料：您可以刪除影子文件中的特定屬性，也可以完全刪除影子。
+ 若要從影子中刪除特定屬性，請更新影子；不過，請將您要刪除的屬性值設定為 `null`。值為 `null` 的欄位會從影子文件中移除。
+ 若要刪除整個影子，請使用 [DeleteThingShadow](device-shadow-rest-api.md#API_DeleteThingShadow) API 或發佈至 [/delete](device-shadow-mqtt.md#delete-pub-sub-topic) 主題。

**注意**  
刪除影子不會一次將其版本編號重設為零。其將於 48 小時後重設為零。

### 從影子文件中刪除屬性
<a name="deleting-shadow-property"></a>

**使用 MQTT 通訊協定從影子刪除屬性**

1. 裝置或用戶端應該有目前的影子文件，以便識別要變更的屬性。如需如何取得目前影子文件的詳細資訊，請參閱 [擷取影子文件](#retrieving-device-shadow)。

1. 裝置或用戶端會訂閱下列 MQTT 主題：
   + `$aws/things/thingName/shadow/name/shadowName/update/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/update/rejected`

1. 裝置或用戶端會發佈 `$aws/things/thingName/shadow/name/shadowName/update` 請求主題，其中包含狀態文件，該文件會將 `null` 值指派給要刪除的影子屬性。只有要變更的屬性需要包含在文件中。這是刪除 `engine` 屬性的文件範例。

   ```
   {
     "state": {
       "desired": {
         "engine": null
       }
     }
   }
   ```

1. 如果更新請求有效， 會 AWS IoT 刪除影子中指定的屬性，並在訊息內文中發佈具有影[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)子文件的 `$aws/things/thingName/shadow/name/shadowName/update/accepted`主題訊息。

1. 如果更新請求無效， 會使用描述錯誤的[錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)影子文件 AWS IoT 發佈具有 `$aws/things/thingName/shadow/name/shadowName/update/rejected`主題的訊息。

**使用 REST API 從影子刪除屬性**

1. 裝置或用戶端會呼叫 `UpdateThingShadow` API，其具有將 `null` 值指派給要刪除之影子屬性的 [請求狀態文件](device-shadow-document.md#device-shadow-example-request-json)。只包含您要在文件中刪除的屬性。這是刪除 `engine` 屬性的文件範例。

   ```
   {
     "state": {
       "desired": {
         "engine": null
       }
     }
   }
   ```

1. 如果請求有效， 會 AWS IoT 傳回 HTTP 成功回應碼和[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)影子文件作為其回應訊息內文。

1. 如果請求無效， 會 AWS IoT 傳回 HTTP 錯誤回應代碼 [錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)作為其回應訊息內文。

### 刪除影子
<a name="deleting-device-shadow"></a>

以下是刪除裝置影子時的一些考量事項。
+ 將裝置的影子狀態設定為 `null` 不會刪除影子。影子版本將在下一次更新時遞增。
+ 刪除裝置的影子並不會刪除物件物件。刪除物件物件也不會刪除對應的裝置影子。
+ 刪除影子不會一次將其版本編號重設為零。其將於 48 小時後重設為零。

**使用 MQTT 通訊協定刪除影子**

1. 裝置或用戶端會訂閱下列 MQTT 主題：
   + `$aws/things/thingName/shadow/name/shadowName/delete/accepted`
   + `$aws/things/thingName/shadow/name/shadowName/delete/rejected`

1. 裝置或用戶端會發佈具有空白訊息緩衝區的 `$aws/things/thingName/shadow/name/shadowName/delete`。

1. 如果刪除請求有效， 會 AWS IoT 刪除影子，並在訊息內文中發佈具有`$aws/things/thingName/shadow/name/shadowName/delete/accepted`主題和縮寫影[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)子文件的訊息。以下是接受的刪除訊息範例：

   ```
   {
     "version": 4,
     "timestamp": 1591057529
   }
   ```

1. 如果更新請求無效， 會使用描述錯誤的[錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)影子文件 AWS IoT 發佈具有 `$aws/things/thingName/shadow/name/shadowName/delete/rejected`主題的訊息。

**使用 REST API 刪除影子**

1. 裝置或用戶端會使用空的訊息緩衝區呼叫 `DeleteThingShadow` API。

1. 如果請求有效， 會在訊息內文中 AWS IoT 傳回 HTTP 成功回應碼和 [/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)以及縮寫[/accepted response state document](device-shadow-document.md#device-shadow-example-response-json-accepted)陰影文件。以下是接受的刪除訊息範例：

   ```
   {
     "version": 4,
     "timestamp": 1591057529
   }
   ```

1. 如果請求無效， 會 AWS IoT 傳回 HTTP 錯誤回應代碼 [錯誤回應文件](device-shadow-document.md#device-shadow-example-error-json)作為其回應訊息內文。