

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

# 教學課程：開發可延遲元件更新的 Greengrass 元件
<a name="defer-component-updates-tutorial"></a>

您可以完成本教學課程，以開發延遲over-the-air部署更新的元件。當您部署更新至裝置時，您可能會想要根據條件延遲更新，例如下列項目：
+ 裝置電池電量低。
+ 裝置正在執行無法中斷的程序或任務。
+ 裝置具有有限或昂貴的網際網路連線。

**注意**  
*元件*是在 AWS IoT Greengrass 核心裝置上執行的軟體模組。元件可讓您將複雜的應用程式建立和管理為分散的建置區塊，以便從一個 Greengrass 核心裝置重複使用。

在此教學課程中，您將執行下列操作：

1. 在開發電腦上安裝 Greengrass 開發套件 CLI (GDK CLI)。GDK CLI 提供可協助您開發自訂 Greengrass 元件的功能。

1. 開發 Hello World 元件，在核心裝置的電池電量低於閾值時延遲元件更新。此元件訂閱使用 [SubscribeToComponentUpdates](ipc-component-lifecycle.md#ipc-operation-subscribetocomponentupdates) IPC 操作來更新通知。收到通知時，它會檢查電池電量是否低於可自訂的閾值。如果電池電量低於閾值，則會使用 [DeferComponentUpdate](ipc-component-lifecycle.md#ipc-operation-defercomponentupdate) IPC 操作將更新延遲 30 秒。您可以使用 GDK CLI 在開發電腦上開發此元件。
**注意**  
此元件會從您在核心裝置上建立的檔案讀取電池電量，以模擬真正的電池，因此您可以在核心裝置上完成此教學課程，而無需電池。

1. 將該元件發佈至 AWS IoT Greengrass 服務。

1. 將該元件從 部署 AWS 雲端 到 Greengrass 核心裝置以進行測試。然後，您可以修改核心裝置上的虛擬電池電量，並建立其他部署，以查看核心裝置在電池電量低時如何延遲更新。

您可以預期在本教學課程中花費 20-30 分鐘。

# 先決條件
<a name="defer-component-updates-tutorial-prerequisites"></a>

為了完成本教學，您需要以下項目：
+  AWS 帳戶：如果您沒有帳戶，請參閱 [設定 AWS 帳戶](setting-up.md#set-up-aws-account)。
+ 具有管理員許可的 AWS Identity and Access Management (IAM) 使用者。
+ 具有網際網路連線的 Greengrass 核心裝置。如需如何設定核心裝置的詳細資訊，請參閱[設定 AWS IoT Greengrass 核心裝置](setting-up.md)。
  + 核心裝置上所有使用者已安裝 [Python](https://www.python.org/downloads/) 3.6 或更新版本，並已新增至`PATH`環境變數。在 Windows 上，您也必須為所有使用者安裝適用於 Windows 的 Python Launcher。
**重要**  <a name="windows-core-device-python-installation"></a>
在 Windows 中，Python 預設不會為所有使用者安裝 。安裝 Python 時，您必須自訂安裝以設定安裝， AWS IoT Greengrass 核心軟體才能執行 Python 指令碼。例如，如果您使用圖形 Python 安裝程式，請執行下列動作：  
選取**安裝所有使用者的啟動器 （建議）**。
選擇 **Customize installation**。
選擇 **Next**。
選取 **Install for all users**。
選取 **Add Python to environment variables**。
選擇 **Install (安裝)**。
如需詳細資訊，請參閱 [Python 3 文件中的在 Windows 上使用](https://docs.python.org/3/using/windows.html) *Python*。
+ 具有網際網路連線的 Windows、macOS 或類似 Unix 的開發電腦。
  + 您的開發電腦上已安裝 [Python](https://www.python.org/downloads/) 3.6 或更新版本。
  + 安裝在開發電腦上的 [Git](https://git-scm.com/)。
  + <a name="development-component-aws-cli-prerequisite"></a>AWS Command Line Interface (AWS CLI) 在開發電腦上安裝並設定 憑證。如需詳細資訊，請參閱*AWS Command Line Interface 《 使用者指南*》中的[安裝、更新和解除安裝 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) 和[設定 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)。
**注意**  
如果您使用 Raspberry Pi 或其他 32 位元 ARM 裝置，則 install AWS CLI V1. AWS CLI V2 不適用於 32 位元 ARM 裝置。如需詳細資訊，請參閱[安裝、更新和解除安裝 AWS CLI 版本 1](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv1.html)。

# 步驟 1：安裝 Greengrass 開發套件 CLI
<a name="install-gdk-cli-defer-updates"></a>

[Greengrass 開發套件 CLI (GDK CLI)](greengrass-development-kit-cli.md) 提供可協助您開發自訂 Greengrass 元件的功能。您可以使用 GDK CLI 來建立、建置和發佈自訂元件。

如果您尚未在開發電腦上安裝 GDK CLI，請完成下列步驟來安裝它。

**安裝最新版本的 GDK CLI**

1. 在開發電腦上，執行下列命令，從其 [GitHub 儲存庫](https://github.com/aws-greengrass/aws-greengrass-gdk-cli)安裝最新版本的 GDK CLI。

   ```
   python3 -m pip install -U git+https://github.com/aws-greengrass/aws-greengrass-gdk-cli.git@v1.6.2
   ```

1. <a name="gdk-cli-verify-installation"></a>執行下列命令來驗證 GDK CLI 是否已成功安裝。

   ```
   gdk --help
   ```

   如果找不到 `gdk`命令，請將其資料夾新增至 PATH。
   + 在 Linux 裝置上，將 `/home/MyUser/.local/bin` 新增至 PATH，並以您的使用者名稱取代 *MyUser*。
   + 在 Windows 裝置上，將 `PythonPath\\Scripts` 新增至 PATH，並將 *PythonPath* 取代為您裝置上的 Python 資料夾路徑。

# 步驟 2：開發延遲更新的元件
<a name="develop-component-defer-updates"></a>

在本節中，您會在 Python 中開發 Hello World 元件，該元件會在核心裝置的電池電量低於部署元件時設定的閾值時延遲元件更新。在此元件中，您會在 AWS IoT Device SDK v2 for Python 中使用[程序間通訊 (IPC) 界面](interprocess-communication.md)。您可以使用 [SubscribeToComponentUpdates](ipc-component-lifecycle.md#ipc-operation-subscribetocomponentupdates) IPC 操作，在核心裝置收到部署時接收通知。然後，您可以使用 [DeferComponentUpdate](ipc-component-lifecycle.md#ipc-operation-defercomponentupdate) IPC 操作，根據裝置的電池電量延遲或確認更新。

**開發延遲更新的 Hello World 元件**

1. 在開發電腦上，為元件原始程式碼建立資料夾。

   ```
   mkdir com.example.BatteryAwareHelloWorld
   cd com.example.BatteryAwareHelloWorld
   ```

1. 使用文字編輯器來建立名為 的檔案`gdk-config.json`。GDK CLI 會從名為 的 [GDK CLI 組態檔案](gdk-cli-configuration-file.md)讀取`gdk-config.json`，以建置和發佈元件。此組態檔案存在於元件資料夾的根目錄中。

   <a name="nano-command-intro"></a>例如，在以 Linux 為基礎的系統上，您可以執行下列命令來使用 GNU nano 來建立 檔案。

   ```
   nano gdk-config.json
   ```

   將下列 JSON 複製到 檔案。
   + 以您的名稱取代 *Amazon*。
   + 將 *us-west-2* 取代為核心裝置運作 AWS 區域 所在的 。GDK CLI 會在此發佈元件 AWS 區域。
   + 將 *greengrass-component-artifacts* 取代為要使用的 S3 儲存貯體字首。當您使用 GDK CLI 發佈元件時，GDK CLI 會使用下列格式，將元件的成品上傳至 S3 儲存貯體，其名稱是從此值 AWS 區域、 和您的 AWS 帳戶 ID 形成：`bucketPrefix-region-accountId`。

     例如，如果您指定 **greengrass-component-artifacts**和 **us-west-2**，且 AWS 帳戶 ID 為 **123456789012**，則 GDK CLI 會使用名為 的 S3 儲存貯體`greengrass-component-artifacts-us-west-2-123456789012`。

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

   組態檔案會指定下列項目：
   + 當 GDK CLI 將 Greengrass 元件發佈至雲端服務時要使用的 AWS IoT Greengrass 版本。 `NEXT_PATCH`指定 在 AWS IoT Greengrass 雲端服務中可用的最新版本之後選擇下一個修補程式版本。如果元件在 AWS IoT Greengrass 雲端服務中還沒有版本，GDK CLI 會使用 `1.0.0`。
   + 元件的建置系統。當您使用`zip`建置系統時，GDK CLI 會將元件的來源封裝成 ZIP 檔案，該檔案會成為元件的單一成品。
   +  AWS 區域 GDK CLI 發佈 Greengrass 元件的 。
   + GDK CLI 上傳元件成品的 S3 儲存貯體字首。

1. 使用文字編輯器在名為 的檔案中建立元件原始程式碼`main.py`。

   <a name="nano-command-intro"></a>例如，在以 Linux 為基礎的系統上，您可以執行下列命令來使用 GNU nano 來建立 檔案。

   ```
   nano main.py
   ```

   將下列 Python 程式碼複製到 檔案。

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

   此 Python 應用程式會執行下列動作：
   + 從您稍後將在核心裝置上建立的虛擬電池電量檔案中讀取核心裝置的電池電量。此虛擬電池電量檔案會模擬真正的電池，因此您可以在沒有電池的核心裝置上完成此教學課程。
   + 讀取電池閾值的命令列引數，以及虛擬電池電量檔案的路徑。元件配方會根據組態參數設定這些命令列引數，因此您可以在部署元件時自訂這些值。
   + 使用適用於 Python 的 vV2中的 IPC 用戶端 V2 與 AWS IoT Greengrass Core 軟體通訊。 [AWS IoT Device SDK](https://github.com/aws/aws-iot-device-sdk-python-v2)相較於原始 IPC 用戶端，IPC 用戶端 V2 可減少您在自訂元件中使用 IPC 所需的程式碼量。
   + 訂閱以使用 [SubscribeToComponentUpdates](ipc-component-lifecycle.md#ipc-operation-subscribetocomponentupdates) IPC 操作更新通知。 AWS IoT Greengrass 核心軟體會在每次部署前後傳送通知。元件每次收到通知時都會呼叫下列函數。如果通知適用於即將進行的部署，元件會檢查電池電量是否低於閾值。如果電池電量低於閾值，元件會使用 [DeferComponentUpdate](ipc-component-lifecycle.md#ipc-operation-defercomponentupdate) IPC 操作將更新延遲 30 秒。否則，如果電池電量未低於閾值，元件會確認更新，因此可以繼續更新。

     ```
     def on_component_update_event(self, event):
         try:
             if event.pre_update_event is not None:
                 if self.is_battery_below_threshold():
                     self.defer_update(event.pre_update_event.deployment_id)
                     print('Deferred update for deployment %s' %
                           event.pre_update_event.deployment_id)
                 else:
                     self.acknowledge_update(
                         event.pre_update_event.deployment_id)
                     print('Acknowledged update for deployment %s' %
                           event.pre_update_event.deployment_id)
             elif event.post_update_event is not None:
                 print('Applied update for deployment')
         except:
             traceback.print_exc()
     ```
**注意**  
Core AWS IoT Greengrass 軟體不會傳送本機部署的更新通知，因此您可以使用 AWS IoT Greengrass 雲端服務來部署此元件來進行測試。

1. 使用文字編輯器在名為 `recipe.json`或 的檔案中建立元件配方`recipe.yaml`。元件*配方*定義元件的中繼資料、預設組態參數和平台特定的生命週期指令碼。

------
#### [ JSON ]

   <a name="nano-command-intro"></a>例如，在以 Linux 為基礎的系統上，您可以執行下列命令來使用 GNU nano 來建立 檔案。

   ```
   nano recipe.json
   ```

   將下列 JSON 複製到 檔案。

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

------
#### [ YAML ]

   <a name="nano-command-intro"></a>例如，在以 Linux 為基礎的系統上，您可以執行下列命令來使用 GNU nano 來建立 檔案。

   ```
   nano recipe.yaml
   ```

   將下列 YAML 複製到 檔案。

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

------

   此配方會指定下列項目：
   + 電池閾值的預設組態參數、Linux 核心裝置上的虛擬電池檔案路徑，以及 Windows 核心裝置上的虛擬電池檔案路徑。
   + 安裝 AWS IoT Device SDK 最新版本 v2 for Python 的`install`生命週期。
   + 在 中執行 Python 應用程式的`run`生命週期`main.py`。
   + 預留位置，例如 `COMPONENT_NAME`和 `COMPONENT_VERSION`，其中 GDK CLI 會在建置元件配方時取代資訊。

   如需元件配方的詳細資訊，請參閱 [AWS IoT Greengrass 元件配方參考](component-recipe-reference.md)。

# 步驟 3：將元件發佈至 AWS IoT Greengrass 服務
<a name="publish-component-defer-updates"></a>

在本節中，您將 Hello World 元件發佈至 AWS IoT Greengrass 雲端服務。在 AWS IoT Greengrass 雲端服務中提供元件之後，您可以將其部署到核心裝置。您可以使用 GDK CLI 將元件從開發電腦發佈至 AWS IoT Greengrass 雲端服務。GDK CLI 會為您上傳元件的配方和成品。

**將 Hello World 元件發佈至 AWS IoT Greengrass 服務**

1. 執行下列命令，使用 GDK CLI 建置元件。[元件建置命令](greengrass-development-kit-cli-component.md#greengrass-development-kit-cli-component-build)會根據 GDK CLI 組態檔案建立配方和成品。在此程序中，GDK CLI 會建立包含元件原始碼的 ZIP 檔案。

   ```
   gdk component build
   ```

   您應該會看到類似下列範例的訊息。

   ```
   [2022-04-28 11:20:16] INFO - Getting project configuration from gdk-config.json
   [2022-04-28 11:20:16] INFO - Found component recipe file 'recipe.yaml' in the  project directory.
   [2022-04-28 11:20:16] INFO - Building the component 'com.example.BatteryAwareHelloWorld' with the given project configuration.
   [2022-04-28 11:20:16] INFO - Using 'zip' build system to build the component.
   [2022-04-28 11:20:16] WARNING - This component is identified as using 'zip' build system. If this is incorrect, please exit and specify custom build command in the 'gdk-config.json'.
   [2022-04-28 11:20:16] INFO - Zipping source code files of the component.
   [2022-04-28 11:20:16] INFO - Copying over the build artifacts to the greengrass component artifacts build folder.
   [2022-04-28 11:20:16] INFO - Updating artifact URIs in the recipe.
   [2022-04-28 11:20:16] INFO - Creating component recipe in 'C:\Users\finthomp\greengrassv2\com.example.BatteryAwareHelloWorld\greengrass-build\recipes'.
   ```

1. 執行下列命令，將元件發佈至 AWS IoT Greengrass 雲端服務。[元件發佈命令](greengrass-development-kit-cli-component.md#greengrass-development-kit-cli-component-publish)會將元件的 ZIP 檔案成品上傳至 S3 儲存貯體。然後，它會更新元件配方中 ZIP 檔案的 S3 URI，並將配方上傳至服務 AWS IoT Greengrass 。在此程序中，GDK CLI 會檢查 AWS IoT Greengrass 雲端服務中已有哪個版本的 Hello World 元件可用，因此可以選擇該版本之後的下一個修補程式版本。如果元件尚不存在，GDK CLI 會使用版本 `1.0.0`。

   ```
   gdk component publish
   ```

   您應該會看到類似下列範例的訊息。輸出會告訴您 GDK CLI 建立的元件版本。

   ```
   [2022-04-28 11:20:29] INFO - Getting project configuration from gdk-config.json
   [2022-04-28 11:20:29] INFO - Found component recipe file 'recipe.yaml' in the  project directory.
   [2022-04-28 11:20:29] INFO - Found credentials in shared credentials file: ~/.aws/credentials
   [2022-04-28 11:20:30] INFO - No private version of the component 'com.example.BatteryAwareHelloWorld' exist in the account. Using '1.0.0' as the next version to create.
   [2022-04-28 11:20:30] INFO - Publishing the component 'com.example.BatteryAwareHelloWorld' with the given project configuration.
   [2022-04-28 11:20:30] INFO - Uploading the component built artifacts to s3 bucket.
   [2022-04-28 11:20:30] INFO - Uploading component artifacts to S3 bucket: greengrass-component-artifacts-us-west-2-123456789012. If this is your first time using this bucket, add the 's3:GetObject' permission to each core device's token exchange role to allow it to download the component artifacts. For more information, see https://docs.aws.amazon.com/greengrass/v2/developerguide/device-service-role.html.
   [2022-04-28 11:20:30] INFO - Not creating an artifacts bucket as it already exists.
   [2022-04-28 11:20:30] INFO - Updating the component recipe com.example.BatteryAwareHelloWorld-1.0.0.
   [2022-04-28 11:20:31] INFO - Creating a new greengrass component com.example.BatteryAwareHelloWorld-1.0.0
   [2022-04-28 11:20:31] INFO - Created private version '1.0.0' of the component in the account.'com.example.BatteryAwareHelloWorld'.
   ```

1. 從輸出複製 S3 儲存貯體名稱。您稍後會使用儲存貯體名稱，以允許核心裝置從此儲存貯體下載元件成品。

1. （選用） 在 AWS IoT Greengrass 主控台中檢視元件，以確認其已成功上傳。請執行下列操作：

   1. 在[AWS IoT Greengrass 主控台](https://console.aws.amazon.com/greengrass)導覽功能表中，選擇**元件**。

   1. 在**元件**頁面上，選擇**我的元件**索引標籤，然後選擇 **com.example.BatteryAwareHelloWorld**。

      在此頁面上，您可以查看元件的配方和有關元件的其他資訊。

1. <a name="core-device-allow-s3-bucket-access-console-intro-1"></a>允許核心裝置存取 S3 儲存貯體中的元件成品。

   <a name="core-device-allow-s3-bucket-access-console-intro-2"></a>每個核心裝置都有一個[核心裝置 IAM 角色](device-service-role.md)，允許它與 互動 AWS IoT 並將日誌傳送到 AWS 雲端。根據預設，此裝置角色不允許存取 S3 儲存貯體，因此您必須建立並連接允許核心裝置從 S3 儲存貯體擷取元件成品的政策。

   <a name="core-device-allow-s3-bucket-access-console-intro-3"></a>如果您裝置的角色已允許存取 S3 儲存貯體，您可以略過此步驟。否則，請建立允許存取的 IAM 政策，並將其連接到角色，如下所示：

   1. <a name="core-device-allow-s3-bucket-access-console-step-1"></a>在 [IAM 主控台](https://console.aws.amazon.com/iam)導覽功能表中，選擇**政策**，然後選擇**建立政策**。

   1. 在 **JSON** 標籤上，用以下政策取代預留位置內容。將 *greengrass-component-artifacts-us-west-2-123456789012* 取代為 GDK CLI 上傳元件成品的 S3 儲存貯體名稱。

      例如，如果您**us-west-2**在 GDK CLI 組態檔案中指定 **greengrass-component-artifacts**和 ，且 AWS 帳戶 ID 為 **123456789012**，則 GDK CLI 會使用名為 的 S3 儲存貯體`greengrass-component-artifacts-us-west-2-123456789012`。

------
#### [ JSON ]

****  

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Action": [
              "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::greengrass-component-artifacts-us-west-2-123456789012/*"
          }
        ]
      }
      ```

------

   1. <a name="core-device-allow-s3-bucket-access-console-step-3"></a>選擇**下一步**。

   1. <a name="core-device-allow-s3-bucket-access-console-step-4"></a>在**政策詳細資訊區段**中，針對**名稱**輸入 **MyGreengrassV2ComponentArtifactPolicy**。

   1. <a name="core-device-allow-s3-bucket-access-console-step-5"></a>選擇**建立政策**。

   1. <a name="core-device-allow-s3-bucket-access-console-step-6"></a>在 [IAM 主控台](https://console.aws.amazon.com/iam)導覽功能表中，選擇**角色**，然後選擇核心裝置的角色名稱。您在安裝 AWS IoT Greengrass 核心軟體時指定了此角色名稱。如果您未指定名稱，則預設值為 `GreengrassV2TokenExchangeRole`。

   1. <a name="core-device-allow-s3-bucket-access-console-step-7"></a>在**許可**下，選擇**新增許可**，然後選擇**連接政策**。

   1. <a name="core-device-allow-s3-bucket-access-console-step-8"></a>在**新增許可**頁面上，選取您建立`MyGreengrassV2ComponentArtifactPolicy`的政策旁的核取方塊，然後選擇**新增許可**。

# 步驟 4：在核心裝置上部署和測試元件
<a name="deploy-component-defer-updates"></a>

在本節中，您將元件部署至核心裝置以測試其功能。在核心裝置上，您可以建立虛擬電池電量檔案來模擬真正的電池。然後，您可以建立其他部署並觀察核心裝置上的元件日誌檔案，以查看元件延遲和確認更新。

**部署和測試延遲更新的 Hello World 元件**

1. 使用文字編輯器來建立虛擬電池電量檔案。此檔案會模擬真正的電池。
   + 在 Linux 核心裝置上，建立名為 的檔案`/home/ggc_user/virtual_battery.json`。執行具有 `sudo` 許可的文字編輯器。
   + 在 Windows 核心裝置上，建立名為 的檔案`C:\Users\ggc_user\virtual_battery.json`。以管理員身分執行文字編輯器。

   <a name="nano-command-intro"></a>例如，在以 Linux 為基礎的系統上，您可以執行下列命令來使用 GNU nano 來建立 檔案。

   ```
   sudo nano /home/ggc_user/virtual_battery.json
   ```

   將下列 JSON 複製到 檔案。

   ```
   {
     "battery_level": 50
   }
   ```

1. 將 Hello World 元件部署至核心裝置。請執行下列操作：

   1. 在[AWS IoT Greengrass 主控台](https://console.aws.amazon.com/greengrass)導覽功能表中，選擇**元件**。

   1. 在**元件**頁面上，選擇**我的元件**索引標籤，然後選擇 **com.example.BatteryAwareHelloWorld**。

   1. 在 **com.example.BatteryAwareHelloWorld** 頁面中，選擇**部署**。

   1. <a name="deploy-component-choose-deployment-step"></a>從**新增至部署**中，選擇要修改的現有部署，或選擇建立新的部署，然後選擇**下一步**。

   1. <a name="deploy-component-choose-target-step"></a>如果您選擇建立新的部署，請選擇部署的目標核心裝置或物件群組。在**指定目標**頁面的**部署目標**下，選擇核心裝置或物件群組，然後選擇**下一步**。

   1. 在**選取元件**頁面上，確認已選取**com.example.BatteryAwareHelloWorld**元件，選擇**下一步**。

   1. 在**設定元件**頁面上，選取 **com.example.BatteryAwareHelloWorld**，然後執行下列動作：

      1. 選擇**設定元件**。

      1. 在**設定com.example.BatteryAwareHelloWorld**模態、**在組態更新**下，在**要合併的組態**中，輸入下列組態更新。

         ```
         {
           "BatteryThreshold": 70
         }
         ```

      1. 選擇**確認**以關閉模態，然後選擇**下一步**。

   1. 在**確認進階設定**頁面的**部署政策**區段的**元件更新政策**下，確認已選取**通知元件**。當您建立新的部署時，預設會選取**通知元件**。

   1. <a name="deploy-component-review-and-deploy-step"></a>在 **Review (檢閱)** 頁面，選擇 **Deploy (部署)**。

      部署可能需要一分鐘的時間才能完成。

1. Core AWS IoT Greengrass 軟體會將 stdout 從元件程序儲存至 `logs` 資料夾中的日誌檔案。執行下列命令來驗證 Hello World 元件是否執行並列印狀態訊息。

------
#### [ Linux or Unix ]

   ```
   sudo tail -f /greengrass/v2/logs/com.example.BatteryAwareHelloWorld.log
   ```

------
#### [ Windows Command Prompt (CMD) ]

   ```
   type C:\greengrass\v2\logs\com.example.BatteryAwareHelloWorld.log
   ```

------
#### [ PowerShell ]

   ```
   gc C:\greengrass\v2\logs\com.example.BatteryAwareHelloWorld.log -Tail 10 -Wait
   ```

------

   您應該會看到類似下列範例的訊息。

   ```
   Hello, World! Battery level (50) is below threshold (70), so the component will defer updates.
   ```
**注意**  
如果檔案不存在，則部署可能尚未完成。如果檔案在 30 秒內不存在，則部署可能會失敗。例如，如果核心裝置沒有從 S3 儲存貯體下載元件成品的許可，就可能發生這種情況。執行下列命令以檢視 AWS IoT Greengrass Core 軟體日誌檔案。此檔案包含 Greengrass 核心裝置部署服務的日誌。  

   ```
   sudo tail -f /greengrass/v2/logs/greengrass.log
   ```

   ```
   type C:\greengrass\v2\logs\greengrass.log
   ```
<a name="windows-cmd-type-observe-logs"></a>`type` 命令會將檔案的內容寫入終端機。多次執行此命令，以觀察 檔案中的變更。

   ```
   gc C:\greengrass\v2\logs\greengrass.log -Tail 10 -Wait
   ```

1. 建立新的核心裝置部署，以確認元件延遲更新。請執行下列操作：

   1. 在[AWS IoT Greengrass 主控台](https://console.aws.amazon.com/greengrass)導覽功能表中，選擇**部署**。

   1. 選擇您先前建立或修改的部署。

   1. 在部署頁面上，選擇**修訂**。

   1. 在**修訂部署**模式中，選擇**修訂部署**。

   1. 在每個步驟選擇**下一步**，然後選擇**部署**。

1. 執行下列命令以再次檢視元件的日誌，並確認其延遲更新。

------
#### [ Linux or Unix ]

   ```
   sudo tail -f /greengrass/v2/logs/com.example.BatteryAwareHelloWorld.log
   ```

------
#### [ Windows Command Prompt (CMD) ]

   ```
   type C:\greengrass\v2\logs\com.example.BatteryAwareHelloWorld.log
   ```

------
#### [ PowerShell ]

   ```
   gc C:\greengrass\v2\logs\com.example.BatteryAwareHelloWorld.log -Tail 10 -Wait
   ```

------

   您應該會看到類似下列範例的訊息。元件會將更新延遲 30 秒，因此元件會重複列印此訊息。

   ```
   Deferred update for deployment 50722a95-a05f-4e2a-9414-da80103269aa.
   ```

1. 使用文字編輯器編輯虛擬電池電量檔案，並將電池電量變更為超過閾值的值，以便部署可以繼續進行。
   + 在 Linux 核心裝置上，編輯名為 的檔案`/home/ggc_user/virtual_battery.json`。執行具有 `sudo` 許可的文字編輯器。
   + 在 Windows 核心裝置上，編輯名為 的檔案`C:\Users\ggc_user\virtual_battery.json`。以管理員身分執行文字編輯器。

   <a name="nano-command-intro"></a>例如，在以 Linux 為基礎的系統上，您可以執行下列命令來使用 GNU nano 來建立 檔案。

   ```
   sudo nano /home/ggc_user/virtual_battery.json
   ```

   將電池電量變更為 `80`。

   ```
   {
     "battery_level": 80
   }
   ```

1. 執行下列命令以再次檢視元件的日誌，並確認其確認更新。

------
#### [ Linux or Unix ]

   ```
   sudo tail -f /greengrass/v2/logs/com.example.BatteryAwareHelloWorld.log
   ```

------
#### [ Windows Command Prompt (CMD) ]

   ```
   type C:\greengrass\v2\logs\com.example.BatteryAwareHelloWorld.log
   ```

------
#### [ PowerShell ]

   ```
   gc C:\greengrass\v2\logs\com.example.BatteryAwareHelloWorld.log -Tail 10 -Wait
   ```

------

   您應該會看到類似下列範例的訊息。

   ```
   Hello, World! Battery level (80) is above threshold (70), so the component will acknowledge updates.
   Acknowledged update for deployment f9499eb2-4a40-40a7-86c1-c89887d859f1.
   ```

您已完成本教學課程。Hello World 元件會根據核心裝置的電池電量延遲或認可更新。如需本教學課程探索主題的詳細資訊，請參閱以下內容：
+ [開發 AWS IoT Greengrass 元件](develop-greengrass-components.md)
+ [將 AWS IoT Greengrass 元件部署至裝置](manage-deployments.md)
+ [使用 AWS IoT Device SDK 與 Greengrass 核、其他元件和 通訊 AWS IoT Core與 Greengrass 核、其他元件和 通訊 AWS IoT Core](interprocess-communication.md)
+ [AWS IoT Greengrass 開發套件命令列介面](greengrass-development-kit-cli.md)