

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

# AWS IoT 教學課程
<a name="iot-tutorials"></a>

 AWS IoT 教學課程分為兩個學習路徑，以支援兩個不同的目標。為目標選擇最佳的學習路徑。
+ 

**您想要建置proof-of-concept，以測試或示範 AWS IoT 解決方案想法**  
若要在裝置上使用 AWS IoT 裝置用戶端示範常見的 IoT 任務和應用程式，請遵循[使用 AWS IoT 裝置用戶端建置示範](iot-tutorials-dc-intro.md)學習路徑。 AWS IoT Device Client 提供裝置軟體，您可以將自己的雲端資源套用至其中，以示範具有最低開發程度的end-to-end解決方案。

  如需有關 AWS IoT 裝置用戶端的資訊，請參閱 [AWS IoT 裝置用戶端](https://github.com/awslabs/aws-iot-device-client#readme)。
+ 

**想了解如何建置生產軟體來部署解決方案**  
若要使用 AWS IoT 裝置開發套件建立符合您特定需求的解決方案軟體，請遵循[使用 AWS IoT 裝置SDKs建置解決方案](iot-tutorials-sdk-intro.md)學習路徑。

  如需可用 AWS IoT 裝置SDKs的詳細資訊，請參閱 [AWS IoT 裝置 SDKs](iot-sdks.md#iot-device-sdks)。如需 AWS SDKs的相關資訊，請參閱[要建置的工具 AWS](https://aws.amazon.com/tools/)。

**Topics**
+ [使用 AWS IoT 裝置用戶端建置示範](iot-tutorials-dc-intro.md)
+ [使用 AWS IoT 裝置SDKs建置解決方案](iot-tutorials-sdk-intro.md)

# 使用 AWS IoT 裝置用戶端建置示範
<a name="iot-tutorials-dc-intro"></a>

此學習路徑中的教學課程將逐步引導您使用 AWS IoT 裝置用戶端開發示範軟體。 AWS IoT Device Client 提供在您的 IoT 裝置上執行的軟體，以測試和示範建置的 IoT 解決方案的各個層面 AWS IoT。

這些教學課程的目標是促進探索和實驗，讓您有信心在開發裝置軟體之前 AWS IoT 支援您的解決方案。

**您會在本教學課程中學到什麼：**
+ 如何準備 Raspberry Pi 以用作具有 的 IoT 裝置 AWS IoT
+ 如何在裝置上使用 AWS IoT 裝置用戶端示範 AWS IoT 功能

在此學習路徑中，您將在自己的 Raspberry Pi 上安裝 AWS IoT 裝置用戶端，並在雲端中建立 AWS IoT 資源以示範 IoT 解決方案想法。雖然此學習路徑中的教學課程會透過使用 Raspberry Pi 來示範功能，但它們會說明目標和程序，以便協助您調整它們來適應其他裝置。

## 使用 AWS IoT 裝置用戶端建置示範的先決條件
<a name="iot-dc-tutorial-overview"></a>

本節說明在此學習路徑中開始教學課程之前，您需要擁有的先決條件。

**若要完成此學習路徑中的教學課程，您需要：**
+ 

**一個 AWS 帳戶**  
如果您有現有 AWS 帳戶，您可以使用現有的 ，但您可能需要新增其他角色或許可，才能使用 AWS IoT 這些教學課程使用的功能。

  如果您需要建立新的 AWS 帳戶，請參閱 [設定 AWS 帳戶](setting-up.md)。
+ 

**Raspberry Pi 或兼容的 IoT 裝置**  
教學課程使用 [Raspberry Pi](https://www.raspberrypi.org/)，因為它有不同的形式，它無處不在，也是一個相對便宜的示範裝置。教學課程已在 [Raspberry Pi 3 Model B\$1](https://www.raspberrypi.com/products/raspberry-pi-3-model-b-plus/)、[Raspberry Pi 4 Model B](https://www.raspberrypi.com/products/raspberry-pi-4-model-b/)，以及在執行 Ubuntu Server 20.04 LTS (HVM) 的 Amazon EC2 執行個體上進行測試。若要使用 AWS CLI 並執行命令，建議您使用最新版的 Raspberry Pi OS ([Raspberry Pi OS (64 位元）](https://www.raspberrypi.com/software/operating-systems/) 或 OS Lite)。較早版本的作業系統可能適用，但我們尚未對其進行測試。
**注意**  
教學課程會說明每個步驟的目標，以便協助您調整它們來適應尚未嘗試過的 IoT 硬體；不過，這些教學課程並不會明確說明如何調整它們來適應其他裝置。
+ 

**熟悉 IoT 裝置的作業系統**  
這些教學課程中的步驟是假設您熟悉使用基本的 Linux 命令和操作 Raspberry Pi 支援的命令列介面。如果不熟悉這些作業，您就需要給自己更多時間來完成教學課程。

  若要完成這些教學課程，您必須了解如何：
  + 安全地執行基本裝置作業，例如組裝和連接元件、將裝置連接至所需電源，以及安裝和移除記憶卡。
  + 在裝置上上傳及下載系統軟體和檔案。如果裝置不使用卸除式儲存裝置 (例如 microSD 卡)，您必須要知道如何連接至裝置，並在裝置上上傳及下載系統軟體和檔案。
  + 將裝置連接至打算使用該裝置的網路上。
  + 使用 SSH 終端機或類似程式從其他電腦連接至裝置。
  + 使用命令列介面來建立、複製、移動、重新命名以及設定裝置上的檔案和目錄許可。
  + 在裝置上安裝新程式。
  + 使用 FTP 或 SCP 等工具在裝置之間傳輸檔案。
+ 

**IoT 解決方案的開發與測試環境**  
教學課程會說明所需的軟體和硬體；不過，教學課程會假設您可以執行可能未明確說明的作業。這類硬體和操作的範例包括：
  + 

**要下載並存放檔案的本機主機電腦**  
對於 Raspberry Pi，這通常是個人電腦或筆記型電腦，可以讀取和寫入 microSD 記憶卡。本機主機電腦必須：
    + 連線到網際網路。
    + 已安裝並設定妥 [AWS CLI](https://aws.amazon.com//cli/)。
    + 擁有支援 AWS 主控台的 Web 瀏覽器。
  + 

**將本機主機電腦連接到裝置，以便與裝置進行通訊、輸入命令及傳輸檔案的方式**  
在 Raspberry Pi 上，這通常是使用 SSH 和 SCP 從本機主機電腦完成。
  + 

**要連接至 IoT 裝置的顯示器和鍵盤**  
這些設備很有幫助，但不需要這些設備就能完成教學課程。
  + 

**本機主機電腦和 IoT 裝置連線至網際網路的方式**  
這可能是連接至網際網路的路由器或閘道的有線或無線網路連線。本機主機也必須能夠連接至 Raspberry Pi。這可能需要它們位於相同的區域網路上。教學課程無法示範如何針對特定裝置或裝置組態進行設定，但是會示範如何測試此連線。
  + 

**存取區域網路的路由器，檢視連網裝置**  
若要完成此學習路徑中的教學課程，您必須能夠找到 IoT 裝置的 IP 地址。

    在區域網路上，您可以透過存取裝置所連線之網路路由器的管理介面來完成這項操作。如果可以在路由器中為裝置指派固定 IP 地址，則可以在每次裝置重新啟動後簡化重新連線的流程。

    如果裝置連接了鍵盤和顯示器，**ifconfig** 可顯示出裝置的 IP 地址。

    如果這些都不可行，您必須在每次重新啟動裝置後找到一種方法來識別出裝置的 IP 地址。

在擁有所有材料之後，請繼續 [教學課程：為裝置用戶端準備 AWS IoT 裝置](iot-dc-prepare-device.md)。

**Topics**
+ [使用 AWS IoT 裝置用戶端建置示範的先決條件](#iot-dc-tutorial-overview)
+ [教學課程：為裝置用戶端準備 AWS IoT 裝置](iot-dc-prepare-device.md)
+ [教學課程：安裝和設定 AWS IoT 裝置用戶端](iot-dc-install-dc.md)
+ [教學課程：示範與 AWS IoT 裝置用戶端的 MQTT 訊息通訊](iot-dc-testconn.md)
+ [教學課程：使用 AWS IoT 裝置用戶端示範遠端動作 （任務）](iot-dc-runjobs.md)
+ [教學課程：執行 AWS IoT Device Client 教學課程後清除](iot-dc-cleanup.md)

# 教學課程：為裝置用戶端準備 AWS IoT 裝置
<a name="iot-dc-prepare-device"></a>

本教學課程會帶您逐步進行 Raspberry Pi 的初始化，準備好用於學習路徑的後續教學課程。

本教學課程的目標是安裝裝置作業系統的當前版本，並確保您可以在開發環境中與裝置進行通訊。

**先決條件**  
開始本教學課程之前，請確定您已備妥[使用 AWS IoT 裝置用戶端建置示範的先決條件](iot-tutorials-dc-intro.md#iot-dc-tutorial-overview)可用且可供使用的項目。

此教學課程約需 90 分鐘方能完成。

**於本教學課程中，您將會：**
+ 安裝和更新裝置的作業系統。
+ 安裝並驗證執行教學課程所需的任何其他軟體。
+ 測試裝置的連線能力並安裝必要的憑證。

完成本教學課程後，下一個教學課程將為使用 裝置用戶端的示範準備 AWS IoT 您的裝置。

**Topics**
+ [安裝和更新裝置的作業系統](iot-dc-prepare-device-sys.md)
+ [在裝置上安裝並驗證所需的軟體](iot-dc-prepare-device-sw.md)
+ [測試您的裝置並儲存 Amazon CA 憑證](iot-dc-prepare-device-test.md)

# 安裝和更新裝置的作業系統
<a name="iot-dc-prepare-device-sys"></a>

本節中的程序是描述如何將 Raspberry Pi 用於其系統磁碟機的 microSD 卡初始化。Raspberry Pi 的 microSD 卡包含其作業系統 (OS) 軟體及其應用程式檔案儲存的空間。如果不使用 Raspberry Pi，請依照裝置的指示安裝並更新裝置的作業系統軟體。

完成本節之後，您應該可以啟動 IoT 裝置，並從本機主機電腦上的終端機程式連線至該裝置。

**必要設備：**
+ 本機開發和測試環境
+ 可以連接至網際網路的 Raspberry Pi 或 IoT 裝置
+ 具有至少 8 GB 容量或足夠儲存作業系統和所需軟體的 microSD 記憶卡。
**注意**  
在為這些練習選取 microSD 卡時，請盡量選擇容量大但體積小的卡片。  
小型 SD 卡的備份和更新速度會更快。在 Raspberry Pi 上，完成這些教學課程不需要超過 8 GB 的 microSD 卡。如果特定應用程式需要更多空間，您在這些教學課程中儲存的較小映像檔案可以調整較大記憶卡上的檔案系統大小，以使用所選記憶卡的所有支援空間。

**選用設備：**
+ 連接到 Raspberry Pi 的 USB 鍵盤
+ HDMI 顯示器和將顯示器至 Raspberry Pi 的纜線

**Topics**
+ [將裝置的作業系統載入至 microSD 卡](#iot-dc-prepare-device-sys-step1)
+ [使用新的作業系統啟動 IoT 裝置](#iot-dc-prepare-device-sys-step2)
+ [將本機主機電腦連接至裝置](#iot-dc-prepare-device-sys-step3)

## 將裝置的作業系統載入至 microSD 卡
<a name="iot-dc-prepare-device-sys-step1"></a>

此程序會使用本機主機電腦，將裝置的作業系統載入至 microSD 卡。

**注意**  
如果裝置的作業系統未使用卸除式儲存媒體，請使用該裝置的程序安裝作業系統，然後繼續進行 [使用新的作業系統啟動 IoT 裝置](#iot-dc-prepare-device-sys-step2)。

**要在 Raspberry Pi 上安裝作業系統**

1. 在本機主機電腦上，下載並解壓縮要使用的 Raspberry Pi 作業系統映像。最新版本可從 [https://www.raspberrypi.com/software/operating-systems/](https://www.raspberrypi.com/software/operating-systems/) 上下載 

**選擇 Raspberry Pi 作業系統的版本**  
本教學課程會使用 **Raspberry Pi OS Lite** 版本，因為這是在此學習路徑中支援這些教學課程的最小版本。這個版本的 Raspberry Pi 作業系統只有一個命令列介面，沒有圖形使用者介面。具有圖形化使用者介面的最新 Raspberry Pi 作業系統版本也可以使用這些教學課程；不過，此學習路徑中描述的程序只會使用命令列介面，以便在 Raspberry Pi 上執行操作。

1. 請將 microSD 卡插入主機電腦。

1. 使用 SD 卡影像工具，將解壓縮的作業系統映像檔案寫入 microSD 卡。

1. 寫入 Raspberry Pi 作業系統映像至 microSD 卡後：

   1. 在命令列視窗或檔案總管視窗中，開啟 microSD 卡上的 BOOT 分割區。

   1. 在 microSD 卡的 BOOT 分割區中，於根目錄中建立一個名為 `ssh`且沒有檔案副檔名和內容的空白檔案。這樣會告知 Raspberry Pi 在它第一次啟動時啟用 SSH 通訊。

1. 退出 microSD 卡並安全地從本機主機電腦移除。

您的 microSD 記憶卡已準備進行 [使用新的作業系統啟動 IoT 裝置](#iot-dc-prepare-device-sys-step2)。

## 使用新的作業系統啟動 IoT 裝置
<a name="iot-dc-prepare-device-sys-step2"></a>

此程序會安裝 microSD 卡，並使用下載的作業系統首次啟動 Raspberry Pi。

**使用新的作業系統啟動 IoT 裝置**

1. 當電源與裝置斷開時，在上一個步驟中將 microSD 卡 ([將裝置的作業系統載入至 microSD 卡](#iot-dc-prepare-device-sys-step1)) 插入 Raspberry Pi。

1. 將裝置連線至有線網路。

1. 這些教學課程將使用 SSH 終端機與本機主機電腦的 Raspberry Pi 進行互動。

   如果也想直接與裝置互動，您可以：

   1. 在將 HDMI 顯示器連接至裝置來查看 Raspberry Pi 的主控台消息之前，您可以將本機主機電腦上的終端機視窗連接至 Raspberry Pi。

   1. 如果想直接與 Raspberry Pi 互動，請將 USB 鍵盤連接至裝置。

1. 連接電源至 Raspberry Pi，接著等待大約一分鐘來進行初始化。

   如果有顯示器連接至 Raspberry Pi，您可以觀看它的啟動過程。

1. 

   找出裝置的 IP 地址：
   + 如果將 HDMI 顯示器連接至 Raspberry Pi，IP 地址會出現在顯示器上的訊息中 
   + 如果能存取 Raspberry Pi 連接的路由器，您可以在路由器的管理介面中查看它的地址。

在取得 Raspberry Pi 的 IP 地址後，您已準備好進行 [將本機主機電腦連接至裝置](#iot-dc-prepare-device-sys-step3)。

## 將本機主機電腦連接至裝置
<a name="iot-dc-prepare-device-sys-step3"></a>

此程序會使用本機主機電腦上的終端程式連接至 Raspberry Pi，並更改其預設密碼。

**將本機主機電腦連接至裝置**

1. 

   在本機主機電腦上，開啟 SSH 終端程式：
   + Windows：`PuTTY`
   + Linux/macOS：`Terminal`
**注意**  
PuTTY 不會在 Windows 上自動安裝。如果電腦中沒有，您需要下載並安裝 PuTTY。

1. 將終端程式連接至 Raspberry Pi 的 IP 地址，並使用其預設憑證登入。

   ```
   username: pi
   password: raspberry
   ```

1. 登入至 Raspberry Pi 之後，變更 `pi` 使用者密碼。

   ```
   passwd
   ```

   依照提示變更密碼。

   ```
   Changing password for pi.
   Current password: raspberry
   New password: YourNewPassword
   Retype new password: YourNewPassword
   passwd: password updated successfully
   ```

在終端視窗收到 Raspberry Pi 命令列提示並更改密碼之後，即表示您已經準備好繼續進行 [在裝置上安裝並驗證所需的軟體](iot-dc-prepare-device-sw.md)。

# 在裝置上安裝並驗證所需的軟體
<a name="iot-dc-prepare-device-sw"></a>

本節中的程序會從[上一節](iot-dc-prepare-device-sys.md)繼續，讓 Raspberry Pi 的作業系統保持在最新狀態，並在 Raspberry Pi 上安裝軟體，該軟體將在下一節中用於建置和安裝 AWS IoT 裝置用戶端。

完成本節後， Raspberry Pi 會擁有最新的作業系統、本學習路徑教學課程所需的軟體，且會根據位置進行設定。

**必要設備：**
+ [上一節](iot-dc-prepare-device-sys.md)中的本機開發和測試環境
+ [上一節](iot-dc-prepare-device-sys.md)中使用的 Raspberry Pi
+ [上一節](iot-dc-prepare-device-sys.md)中的 microSD 記憶卡

**注意**  
Raspberry Pi Model 3\$1 和 Raspberry Pi Model 4 可執行此學習路徑中描述的所有命令。如果您的 IoT 裝置無法編譯軟體或執行 AWS Command Line Interface，您可能需要在本機主機電腦上安裝必要的編譯器，才能建置軟體，然後將其傳輸至 IoT 裝置。如需有關如何為裝置安裝和建置軟體的詳細資訊，請參閱裝置軟體的說明文件。

**Topics**
+ [更新作業系統軟體](#iot-dc-prepare-device-sw-step1)
+ [安裝必要的應用程式和程式庫](#iot-dc-prepare-device-sw-step2)
+ [(選用) 儲存 microSD 卡映像](#iot-dc-prepare-device-sw-step3)

## 更新作業系統軟體
<a name="iot-dc-prepare-device-sw-step1"></a>

此程序會更新作業系統軟體。

**更新 Raspberry Pi 上的作業系統軟體**

在本機主機電腦的終端機視窗中執行這些步驟。

1. 輸入這些命令來更新 Raspberry Pi 上的系統軟體。

   ```
   sudo apt-get -y update
   sudo apt-get -y upgrade
   sudo apt-get -y autoremove
   ```

1. 更新 Raspberry Pi 的地區設定和時區設定 (選用)。

   輸入此指令來更新裝置的地區設定和時區設定。

   ```
   sudo raspi-config
   ```

   1. 若要設定裝置的地區設定：

      1. 在 **Raspberry Pi Software Configuration Tool (raspi-config)** (Raspberry Pi 軟體組態工具 (raspi-config)) 畫面中，選擇選項 **5**。

         **`5 Localisation Options Configure language and regional settings`**

         使用 Tab 鍵來移動至 **<Select>** (選擇)，然後按 space bar。

      1. 在當地語系化選項選單中，選擇選項 **L1**。

         **`L1 Locale Configure language and regional settings`**

         使用 Tab 鍵來移動至 **<Select>** (選擇)，然後按 space bar。

      1. 在地區選項清單中，使用方向鍵捲動並使用 space bar 標記所需地區，選擇要在 Raspberry Pi 上安裝的地區設定。

         建議為美國選擇 **`en_US.UTF-8`**。

      1. 選取裝置的地區後，請使用 Tab 鍵選擇 **<OK>** (確定)，然後按 space bar 來顯示 **Configuring locales** (設定地區設定) 的確認頁面。

   1. 若要設定裝置的時區：

      1. 在 **raspi-config** 畫面中，選擇選項 **5**。

         **`5 Localisation Options Configure language and regional settings`**

         使用 Tab 鍵來移動至 **<Select>** (選擇)，然後按 space bar。

      1. 在當地語系化選項選單中，使用方向鍵選擇選項 **L2**：

         **`L2 time zone Configure time zone`**

         使用 Tab 鍵來移動至 **<Select>** (選擇)，然後按 space bar。

      1. 在 **Configuring tzdata** 選單中，從清單中選擇地理區域。

         使用 Tab 鍵來移動至 **<OK>** (確定)，然後按 space bar。

      1. 在城市清單中，使用方向鍵來選擇您所在時區的城市。

         若要設定時區，請使用 Tab 鍵來移動至 **<OK>** (確定)，然後按 space bar。

   1. 完成更新設定時，請使用 Tab 鍵來移動至 **<Finish>** (完成)，然後按 space bar 來關閉 **raspi-config** 應用程式。

1. 輸入此命令來重新啟動 Raspberry Pi。

   ```
   sudo shutdown -r 0
   ```

1. 等待 Raspberry Pi 重新啟動。

1. 待 Raspberry Pi 重新啟動後，請將本機主機電腦上的終端機視窗重新連接至 Raspberry Pi。

Raspberry Pi 系統軟體已設定完成，您已經準備好繼續進行 [安裝必要的應用程式和程式庫](#iot-dc-prepare-device-sw-step2)。

## 安裝必要的應用程式和程式庫
<a name="iot-dc-prepare-device-sw-step2"></a>

此程序會安裝後續教學課程使用的應用程式軟體和程式庫。

如果正在使用 Raspberry Pi，或者如果可以在 IoT 裝置上編譯所需軟體，請在本機主機電腦上的終端機視窗中執行這些步驟。如果必須在本機主機電腦上編譯 IoT 裝置的軟體，請檢閱 IoT 裝置的軟體說明文件，取得如何在裝置上執行這些步驟的相關資訊。

**在 Raspberry Pi 上安裝應用程式軟體和程式庫**

1. 輸入此指令來安裝應用程式軟體和程式庫。

   ```
   sudo apt-get -y install build-essential libssl-dev cmake unzip git python3-pip
   ```

1. 輸入這些指令來確認是否已安裝正確版本的軟體。

   ```
   gcc --version
   cmake --version
   openssl version
   git --version
   ```

1. 

   確認已安裝下列版本的應用程式軟體：
   + `gcc`：9.3.0 或更新版本
   + `cmake`：3.10.x 或更新版本
   + `OpenSSL`：1.1.1 或更新版本
   + `git`：2.20.1 或更新版本

如果 Raspberry Pi 有所需應用程式軟體的可接受版本，您就可以繼續進行 [(選用) 儲存 microSD 卡映像](#iot-dc-prepare-device-sw-step3)。

## (選用) 儲存 microSD 卡映像
<a name="iot-dc-prepare-device-sw-step3"></a>

在此學習路徑的整個教學課程中，您會遇到這些程序來將 Raspberry Pi 的 microSD 卡映像儲存至本機主機電腦上的檔案。雖然鼓勵這樣操作，但這不是必要任務。透過在建議位置上儲存 microSD 卡映像，您可以略過此學習路徑中儲存點之前的程序；若您發現需要重試某些項目，這就可以節省時間。未定期儲存 microSD 卡映像的結果是，當 microSD 卡損壞或意外錯誤設定應用程式或其設定時，您可能需要從頭開始重新開始學習路徑中的教學課程。

此時，Raspberry Pi 的 microSD 卡已經擁有更新的作業系統和加載的基本應用程式軟體。您現在可以將 microSD 卡的內容儲存至檔案，節省完成上述步驟所花費的時間。擁有裝置 microSD 卡映像目前的映像，可讓您從此開始繼續或重試教學課程或程序，無需從頭開始安裝和更新軟體。

**將 microSD 卡映像儲存至檔案**

1. 輸入此命令來關閉 Raspberry Pi。

   ```
   sudo shutdown -h 0
   ```

1. Raspberry Pi 完全關閉後，請移除其電源。

1. 從 Raspberry Pi 中取出 microSD 卡。

1. 在本機主機電腦上：

   1. 插入 microSD 卡。

   1. 使用 SD 卡映像工具，將 microSD 卡的映像儲存至檔案中。

   1. 儲存 microSD 卡的映像後，請從本機主機電腦中退出記憶卡。

1. 在 Raspberry Pi 斷開電源後，將 microSD 卡插入 Raspberry Pi。

1. 將電源連接至 Raspberry Pi。

1. 等待大約一分鐘後，在本機主機電腦上重新連線至連接至 Raspberry Pi 的本機主機電腦終端機視窗，然後登入 Raspberry Pi。

# 測試您的裝置並儲存 Amazon CA 憑證
<a name="iot-dc-prepare-device-test"></a>

本節中的程序會從[上一節](iot-dc-prepare-device-sw.md)繼續，安裝用於驗證您連線的 AWS Command Line Interface 和 Certificate Authority 憑證 AWS IoT Core。

完成本節後，您會知道 Raspberry Pi 具有安裝 AWS IoT 裝置用戶端所需的系統軟體，且其具有與網際網路的運作連線。

**必要設備：**
+ [上一節](iot-dc-prepare-device-sw.md)中的本機開發和測試環境
+ [上一節](iot-dc-prepare-device-sw.md)中使用的 Raspberry Pi
+ [上一節](iot-dc-prepare-device-sw.md)中的 microSD 記憶卡

**Topics**
+ [安裝 AWS Command Line Interface](#iot-dc-prepare-device-test-step1)
+ [設定您的 AWS 帳戶 登入資料](#iot-dc-prepare-device-test-step2)
+ [下載 Amazon 根憑證授權機構憑證](#iot-dc-prepare-device-test-step3)
+ [(選用) 儲存 microSD 卡映像](#iot-dc-prepare-device-test-step4)

## 安裝 AWS Command Line Interface
<a name="iot-dc-prepare-device-test-step1"></a>

此程序會將 安裝 AWS CLI 到您的 Raspberry Pi。

如果使用的是 Raspberry Pi，或者如果可以在 IoT 裝置上編譯軟體，請在本機主機電腦上的終端機視窗中執行這些步驟。如果必須在本機主機電腦上編譯 IoT 裝置的軟體，請檢閱 IoT 裝置的軟體說明文件，取得其所需之程式庫的相關資訊。

**在 Raspberry Pi AWS CLI 上安裝**

1. 執行這些命令來下載和安裝 AWS CLI。

   ```
   export PATH=$PATH:~/.local/bin # configures the path to include the directory with the AWS CLI
   git clone https://github.com/aws/aws-cli.git # download the AWS CLI code from GitHub
   cd aws-cli && git checkout v2 # go to the directory with the repo and checkout version 2
   pip3 install -r requirements.txt # install the prerequisite software
   ```

1. 執行此命令來安裝 AWS CLI。此命令最多需要 15 分鐘的時間即可完成。

   ```
   pip3 install . # install the AWS CLI 
   ```

1. 執行此命令以確認 AWS CLI 已安裝正確的 版本。

   ```
   aws --version
   ```

   的版本 AWS CLI 應為 2.2 或更新版本。

如果 AWS CLI 顯示其目前版本，您就可以繼續 [設定您的 AWS 帳戶 登入資料](#iot-dc-prepare-device-test-step2)。

## 設定您的 AWS 帳戶 登入資料
<a name="iot-dc-prepare-device-test-step2"></a>

在此程序中，您將取得登入資料並新增這些 AWS 帳戶 登入資料，以便在 Raspberry Pi 上使用。

**將 AWS 帳戶 登入資料新增至您的裝置**

1. 從 取得**存取金鑰 ID** 和**私密存取金鑰** AWS 帳戶 ，以驗證 AWS CLI 裝置上的 。

   如果您是初次使用 AWS IAM，https：//[https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/ ](https://aws.amazon.com/premiumsupport/knowledge-center/create-access-key/)會說明在 AWS 主控台中執行的程序，以建立 AWS 要在裝置上使用的 IAM 登入資料。

1. 在連接至 Raspberry Pi 的本機主機電腦終端機視窗上，以及裝置的 **Access Key ID** (存取金鑰 ID) 和 **Secret Access Key** (私密存取金鑰) 憑證：

   1. 使用此命令執行 AWS configure 應用程式：

      ```
      aws configure
      ```

   1. 出現提示時，請輸入憑證和組態資訊：

      ```
      AWS Access Key ID: your Access Key ID
      AWS Secret Access Key: your Secret Access Key
      Default region name: your AWS 區域 code
      Default output format: json
      ```

1. 執行此命令來測試裝置對 AWS 帳戶 和 AWS IoT Core 端點的存取。

   ```
   aws iot describe-endpoint --endpoint-type iot:Data-ATS
   ```

   它應該會傳回您的 AWS 帳戶特定 AWS IoT 資料端點，例如此範例：

   ```
   {
       "endpointAddress": "a3EXAMPLEffp-ats.iot.us-west-2.amazonaws.com"
   }
   ```

如果您看到 AWS 帳戶特定的 AWS IoT 資料端點，您的 Raspberry Pi 具有繼續 的連線能力和許可[下載 Amazon 根憑證授權機構憑證](#iot-dc-prepare-device-test-step3)。

**重要**  
您的 AWS 帳戶 登入資料現在會存放在 Raspberry Pi 中的 microSD 卡上。雖然這可讓您在未來 AWS 輕鬆地與 互動，以及您將在這些教學課程中建立的軟體互動，但在預設情況下，它們也會儲存在您在此步驟之後建立的任何 microSD 卡映像中並複製。  
為了保護 AWS 帳戶 登入資料的安全性，在您儲存任何其他 microSD 卡映像之前，請考慮`aws configure`再次執行 並輸入**存取金鑰 ID** 和**私密存取金鑰**的隨機字元來清除登入資料，以防止您的 AWS 帳戶 登入資料洩露。  
如果您發現不小心儲存了 AWS 帳戶 登入資料，您可以在 IAM AWS 主控台中停用登入資料。

## 下載 Amazon 根憑證授權機構憑證
<a name="iot-dc-prepare-device-test-step3"></a>

此程序會下載並儲存 Amazon 根憑證憑證授權機構 (CA) 的憑證副本。下載並儲存此憑證以供後續教學課程使用，也可以測試裝置與 AWS 服務之間的連線能力。

**下載並儲存 Amazon 根憑證授權機構憑證**

1. 執行此命令，為憑證建立目錄。

   ```
   mkdir ~/certs
   ```

1. 執行此命令來下載 Amazon 根憑證授權機構憑證。

   ```
   curl -o ~/certs/AmazonRootCA1.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem
   ```

1. 執行這些命令來設定憑證目錄及其檔案的存取權。

   ```
   chmod 745 ~
   chmod 700 ~/certs
   chmod 644 ~/certs/AmazonRootCA1.pem
   ```

1. 執行此命令來查看新目錄中的憑證授權機構憑證檔案。

   ```
   ls -l ~/certs
   ```

   您應該會看到類似這樣的項目。日期和時間會有所不同；不過，檔案大小和所有其他資訊應該與此處所示相同。

   ```
   -rw-r--r-- 1 pi pi 1188 Oct 28 13:02 AmazonRootCA1.pem
   ```

   如果檔案大小不是 `1188`，請檢查 **curl** 命令參數。您可能下載了不正確的檔案。

## (選用) 儲存 microSD 卡映像
<a name="iot-dc-prepare-device-test-step4"></a>

此時，Raspberry Pi 的 microSD 卡已經擁有更新的作業系統和加載的基本應用程式軟體。

**將 microSD 卡映像儲存至檔案**

1. 在本機主機電腦上的終端機視窗中清除 AWS 憑證。

   1. 使用此命令執行 AWS configure 應用程式：

      ```
      aws configure
      ```

   1. 出現提示時，請取代憑證。您可以按 **Enter** 鍵，讓 **Default region name** (預設區域名稱) 和 **Default output format** (預設輸出格式) 保持不變。

      ```
      AWS Access Key ID [****************YT2H]: XYXYXYXYX
      AWS Secret Access Key [****************9plH]: XYXYXYXYX
      Default region name [us-west-2]: 
      Default output format [json]:
      ```

1. 輸入此命令來關閉 Raspberry Pi。

   ```
   sudo shutdown -h 0
   ```

1. Raspberry Pi 完全關閉之後，移除其電源連接器。

1. 從裝置中取出 microSD 卡。

1. 在本機主機電腦上：

   1. 插入 microSD 卡。

   1. 使用 SD 卡映像工具，將 microSD 卡的映像儲存至檔案中。

   1. 儲存 microSD 卡的映像後，請從本機主機電腦中退出記憶卡。

1. 在 Raspberry Pi 斷開電源後，將 microSD 卡插入 Raspberry Pi。

1. 將電源連接至裝置。

1. 大約一分鐘後，在本機主機電腦上重新啟動終端機視窗工作階段，然後登入裝置。

   **還不要重新輸入您的 AWS 帳戶 登入資料。**

在重新啟動並登入至 Raspberry Pi 之後，您就可以繼續進行 [教學課程：安裝和設定 AWS IoT 裝置用戶端](iot-dc-install-dc.md)。

# 教學課程：安裝和設定 AWS IoT 裝置用戶端
<a name="iot-dc-install-dc"></a>

本教學課程會逐步解說 AWS IoT 裝置用戶端的安裝和組態，以及您將在此和其他示範中使用的 AWS IoT 資源建立。

**若要開始此教學課程：**
+ 準備好[先前教學課程](iot-dc-prepare-device.md)中所述的本機主機電腦和 Raspberry Pi。

此教學課程約需 90 分鐘方能完成。

**完成此主題時：**
+ 您的 IoT 裝置已準備好在其他 AWS IoT 裝置用戶端示範中使用。
+ 您將會在 中佈建 IoT 裝置 AWS IoT Core。
+ 您會在裝置上下載並安裝 AWS IoT 裝置用戶端。
+ 您已經儲存了裝置 microSD 卡的映像，以供後續教學課程使用。

**必要設備：**
+ [上一節](iot-dc-prepare-device-test.md)中的本機開發和測試環境
+ [上一節](iot-dc-prepare-device-test.md)中使用的 Raspberry Pi
+ [上一節](iot-dc-prepare-device-test.md)中使用的 Raspberry Pi microSD 記憶卡

**Topics**
+ [下載並儲存 AWS IoT 裝置用戶端](iot-dc-install-download.md)
+ [在 中佈建 Raspberry Pi AWS IoT](iot-dc-install-provision.md)
+ [設定 AWS IoT 裝置用戶端以測試連線](iot-dc-install-configure.md)

# 下載並儲存 AWS IoT 裝置用戶端
<a name="iot-dc-install-download"></a>

本節中的程序會下載 AWS IoT 裝置用戶端、編譯裝置用戶端，並將其安裝在 Raspberry Pi 上。測試安裝後，您可以儲存 Raspberry Pi 的 microSD 卡映像，以便在再次嘗試教學課程時使用。

**Topics**
+ [下載並建置 AWS IoT 裝置用戶端](#iot-dc-install-dc-download)
+ [建立教學課程所使用的目錄](#iot-dc-install-dc-files)
+ [(選用) 儲存 microSD 卡映像](#iot-dc-install-dc-save)

## 下載並建置 AWS IoT 裝置用戶端
<a name="iot-dc-install-dc-download"></a>

此程序會在 Raspberry Pi 上安裝 AWS IoT 裝置用戶端。

在連接至 Raspberry Pi 本機主機電腦上的終端機視窗中執行這些命令。

**在 Raspberry Pi 上安裝 AWS IoT 裝置用戶端**

1. 輸入這些命令，在您的 Raspberry Pi 上下載並建置 AWS IoT 裝置用戶端。

   ```
   cd ~
   git clone https://github.com/awslabs/aws-iot-device-client aws-iot-device-client
   mkdir ~/aws-iot-device-client/build && cd ~/aws-iot-device-client/build
   cmake ../
   ```

1. 執行此命令來建置 AWS IoT 裝置用戶端。此命令最多需要 15 分鐘的時間即可完成。

   ```
   cmake --build . --target aws-iot-device-client
   ```

   顯示為 AWS IoT Device Client 編譯的警告訊息可以忽略。

   這些教學課程已在 2021 年 10 月 30 日版本 Raspberry Pi OS (bullseye) 的 **gcc**2021 年 10 月 30 日版本 (Raspbian 8.3.0-6\$1rpi1) 8.3.0 的 Raspberry Pi OS (buster) 的 2021 年 5 月 7 日使用建置於 的 AWS IoT Device Client **gcc**(Raspbian 10.2.1-6\$1rpi1) 10.2.1 20210110 進行測試。

1.  AWS IoT 裝置用戶端完成建置後，請執行此命令來測試它。

   ```
   ./aws-iot-device-client --help
   ```

如果您看到 AWS IoT Device Client 的命令列說明， AWS IoT 表示 Device Client 已成功建置並準備好供您使用。

## 建立教學課程所使用的目錄
<a name="iot-dc-install-dc-files"></a>

此程序會在 Raspberry Pi 上建立目錄，用來存放教學課程在此學習路徑中使用的檔案。

**若要在此學習路徑中建立教學課程所使用的目錄：**

1. 執行這些命令來建立必要的目錄。

   ```
   mkdir ~/dc-configs
   mkdir ~/policies
   mkdir ~/messages
   mkdir ~/certs/testconn
   mkdir ~/certs/pubsub
   mkdir ~/certs/jobs
   ```

1. 執行這些命令來設定新目錄的許可。

   ```
   chmod 745 ~
   chmod 700 ~/certs/testconn
   chmod 700 ~/certs/pubsub
   chmod 700 ~/certs/jobs
   ```

建立這些目錄並設定其許可後，請繼續進行 [(選用) 儲存 microSD 卡映像](#iot-dc-install-dc-save)。

## (選用) 儲存 microSD 卡映像
<a name="iot-dc-install-dc-save"></a>

此時，Raspberry Pi 的 microSD 卡具有更新的作業系統、基本應用程式軟體和 AWS IoT 裝置用戶端。

如果想再次嘗試這些練習和教學課程，可以略過上述程序，方法是將隨此程序儲存的 microSD 卡映像寫入新的 microSD 卡，然後繼續進行 [在 中佈建 Raspberry Pi AWS IoT](iot-dc-install-provision.md)。

**若要將 microSD 記憶卡映像儲存至檔案中：**

在連接至 Raspberry Pi 本機主機電腦上的終端機視窗中：

1. 確認您的 AWS 帳戶 登入資料尚未儲存。

   1. 使用此命令執行 AWS configure 應用程式：

      ```
      aws configure
      ```

   1. 如果憑證已儲存 (若顯示在提示中)，請在提示出現時輸入 **XYXYXYXYX** 字串，如下所示。將 **Default region name** (預設區域名稱) 和 **Default output format** (預設輸出格式) 保留為空白。

      ```
      AWS Access Key ID [****************YXYX]: XYXYXYXYX
      AWS Secret Access Key [****************YXYX]: XYXYXYXYX
      Default region name: 
      Default output format:
      ```

1. 輸入此命令來關閉 Raspberry Pi。

   ```
   sudo shutdown -h 0
   ```

1. Raspberry Pi 完全關閉之後，移除其電源連接器。

1. 從裝置中取出 microSD 卡。

1. 在本機主機電腦上：

   1. 插入 microSD 卡。

   1. 使用 SD 卡映像工具，將 microSD 卡的映像儲存至檔案中。

   1. 儲存 microSD 卡的映像後，請從本機主機電腦中退出記憶卡。

您可以在 [在 中佈建 Raspberry Pi AWS IoT](iot-dc-install-provision.md) 中繼續使用此 microSD 卡。

# 在 中佈建 Raspberry Pi AWS IoT
<a name="iot-dc-install-provision"></a>

本節中的程序會從已安裝 和 AWS IoT 裝置用戶端的已儲存 microSD AWS CLI 映像開始，並建立佈建 Raspberry Pi AWS IoT 的資源和裝置憑證 AWS IoT。

## 在 Raspberry Pi 中安裝 microSD 卡
<a name="iot-dc-install-dc-restore"></a>

此程序會安裝已載入 Raspberry Pi 並設定必要軟體的 microSD 卡，並設定您的 ， AWS 帳戶 以便您可以繼續此學習路徑中的教學課程。

使用 [(選用) 儲存 microSD 卡映像](iot-dc-install-download.md#iot-dc-install-dc-save) 中的 microSD 卡，其中包含此學習路徑中的練習和教學課程所需的軟體。

**在 Raspberry Pi 安裝 microSD 卡**

1. 在 Raspberry Pi 斷開電源後，將 microSD 卡插入 Raspberry Pi。

1. 將電源連接至 Raspberry Pi。

1. 大約一分鐘後，在本機主機電腦上重新啟動終端機視窗工作階段，然後登入 Raspberry Pi。

1. 在本機主機電腦的終端機視窗中，使用 Raspberry Pi 的 **Access Key ID** (存取金鑰 ID) 和 **Secret Access Key** (私密存取金鑰) 憑證：

   1. 使用此命令執行 AWS configure 應用程式：

      ```
      aws configure
      ```

   1. 出現提示時，輸入您的 AWS 帳戶 登入資料和組態資訊：

      ```
      AWS Access Key ID [****************YXYX]: your Access Key ID
      AWS Secret Access Key [****************YXYX]: your Secret Access Key
      Default region name [us-west-2]: your AWS 區域 code
      Default output format [json]: json
      ```

還原 AWS 帳戶 登入資料後，您就可以繼續 [在 中佈建您的裝置 AWS IoT Core](#iot-dc-install-dc-provision)。

## 在 中佈建您的裝置 AWS IoT Core
<a name="iot-dc-install-dc-provision"></a>

本節中的程序會建立佈建 Raspberry Pi AWS IoT 的資源 AWS IoT。建立這些資源時，系統會要求您記錄各種資訊。裝置 AWS IoT 用戶端組態會在下一個程序中使用此資訊。

若要讓您的 Raspberry Pi 使用 AWS IoT，必須進行佈建。佈建是建立和設定支援 Raspberry Pi 作為 IoT 裝置所需的 AWS IoT 資源的程序。

在 Raspberry Pi 開啟電源和重新啟動之後，請在本機主機電腦上的終端機視窗中連接至 Raspberry Pi 並完成這些程序。

**Topics**
+ [建立並下載裝置憑證檔案](#iot-dc-install-dc-provision-certs)
+ [建立 AWS IoT 資源](#iot-dc-install-dc-provision-resources)

### 建立並下載裝置憑證檔案
<a name="iot-dc-install-dc-provision-certs"></a>

此程序會建立此示範的裝置憑證檔案。

**為 Raspberry Pi 建立並下載裝置憑證檔案**

1. 在本機主機電腦的終端機視窗中，輸入這些命令來建立裝置的裝置憑證檔案。

   ```
   mkdir ~/certs/testconn
   aws iot create-keys-and-certificate \
   --set-as-active \
   --certificate-pem-outfile "~/certs/testconn/device.pem.crt" \
   --public-key-outfile "~/certs/testconn/public.pem.key" \
   --private-key-outfile "~/certs/testconn/private.pem.key"
   ```

   此命令會傳回類似以下的回應。記錄 `certificateArn` 值，供之後使用。

   ```
   {
       "certificateArn": "arn:aws:iot:us-west-2:57EXAMPLE833:cert/76e7e4edb3e52f52334be2f387a06145b2aa4c7fcd810f3aea2d92abc227d269",
       "certificateId": "76e7e4edb3e52f5233EXAMPLE7a06145b2aa4c7fcd810f3aea2d92abc227d269",
       "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIDWTCCAkGgAwIBAgI_SHORTENED_FOR_EXAMPLE_Lgn4jfgtS\n-----END CERTIFICATE-----\n",
       "keyPair": {
           "PublicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BA_SHORTENED_FOR_EXAMPLE_ImwIDAQAB\n-----END PUBLIC KEY-----\n",
           "PrivateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQE_SHORTENED_FOR_EXAMPLE_T9RoDiukY\n-----END RSA PRIVATE KEY-----\n"
       }
   }
   ```

1. 輸入下列命令來設定憑證目錄及其檔案的許可。

   ```
   chmod 745 ~
   chmod 700 ~/certs/testconn
   chmod 644 ~/certs/testconn/*
   chmod 600 ~/certs/testconn/private.pem.key
   ```

1. 執行此命令來檢閱憑證目錄和檔案的許可。

   ```
   ls -l ~/certs/testconn
   ```

   命令的輸出應該與您在此處看到的相同，但檔案日期和時間會有所不同。

   ```
   -rw-r--r-- 1 pi pi 1220 Oct 28 13:02 device.pem.crt
   -rw------- 1 pi pi 1675 Oct 28 13:02 private.pem.key
   -rw-r--r-- 1 pi pi  451 Oct 28 13:02 public.pem.key
   ```

此時，您已在 Raspberry Pi 上安裝了裝置憑證檔案，可以繼續進行 [建立 AWS IoT 資源](#iot-dc-install-dc-provision-resources)。

### 建立 AWS IoT 資源
<a name="iot-dc-install-dc-provision-resources"></a>

此程序 AWS IoT 透過建立裝置存取 AWS IoT 功能和服務所需的資源，在 中佈建您的裝置。

**在 中佈建您的裝置 AWS IoT**

1. 在本機主機電腦的終端機視窗中輸入下列命令，取得 AWS 帳戶裝置資料端點的地址。

   ```
   aws iot describe-endpoint --endpoint-type IoT:Data-ATS
   ```

   先前步驟的命令會傳回類似以下的回應：記錄 `endpointAddress` 值，供之後使用。

   ```
   {
       "endpointAddress": "a3qjEXAMPLEffp-ats.iot.us-west-2.amazonaws.com"
   }
   ```

1. 輸入此命令來建立 Raspberry Pi 的 AWS IoT 物件資源。

   ```
   aws iot create-thing --thing-name "DevCliTestThing"
   ```

   如果您的 AWS IoT 物件資源已建立，命令會傳回類似這樣的回應。

   ```
   {
       "thingName": "DevCliTestThing",
       "thingArn": "arn:aws:iot:us-west-2:57EXAMPLE833:thing/DevCliTestThing",
       "thingId": "8ea78707-32c3-4f8a-9232-14bEXAMPLEfd"
   }
   ```

1. 在終端機視窗中：

   1. 開啟文字編輯器，例如 `nano`。

   1. 複製此 JSON 政策文件並將其貼入開啟的文字編輯器中。  
****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Publish",
                      "iot:Subscribe",
                      "iot:Receive",
                      "iot:Connect"
                  ],
                  "Resource": [
                      "*"
                  ]
              }
          ]
      }
      ```
**注意**  
本政策文件會慷慨地授予每個資源許可，以便進行連線、接收、發佈和訂閱。通常，政策只會授予特定資源許可，以便執行特定動作。不過，對於初始裝置連線能力測試，這個過度寬鬆的政策能夠在此測試期間盡力降低出現存取問題的機率。在後續教學課程中，將使用範圍較窄的政策文件來示範政策設計的更佳實務。

   1. 將文字編輯器中的檔案儲存為 **\$1/policies/dev\$1cli\$1test\$1thing\$1policy.json**。

1. 執行此命令以使用先前步驟的政策文件來建立 AWS IoT 政策。

   ```
   aws iot create-policy \
   --policy-name "DevCliTestThingPolicy" \
   --policy-document "file://~/policies/dev_cli_test_thing_policy.json"
   ```

   如果建立此政策，此命令會傳回類似以下的回應。

   ```
   {
       "policyName": "DevCliTestThingPolicy",
       "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/DevCliTestThingPolicy",
       "policyDocument": "{\n    \"Version\": \"2012-10-17\",		 	 	 \n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"iot:Publish\",\n                \"iot:Subscribe\",\n                \"iot:Receive\",\n                \"iot:Connect\"\n            ],\n            \"Resource\": [\n                \"*\"\n            ]\n        }\n    ]\n}\n",
       "policyVersionId": "1"
   }
   ```

1. 執行此命令，將此政策連接至裝置憑證。使用之前儲存的 `certificateArn` 值來取代 `certificateArn`

   ```
   aws iot attach-policy \
   --policy-name "DevCliTestThingPolicy" \
   --target "certificateArn"
   ```

   若成功，此命令不會傳回任何內容。

1. 執行此命令，將裝置憑證連接至 AWS IoT 物件資源。使用之前儲存的 `certificateArn` 值來取代 `certificateArn`

   ```
   aws iot attach-thing-principal \
   --thing-name "DevCliTestThing" \
   --principal "certificateArn"
   ```

   若成功，此命令不會傳回任何內容。

成功在 中佈建裝置後 AWS IoT，您就可以繼續 [設定 AWS IoT 裝置用戶端以測試連線](iot-dc-install-configure.md)。

# 設定 AWS IoT 裝置用戶端以測試連線
<a name="iot-dc-install-configure"></a>

本節中的程序會將 AWS IoT 裝置用戶端設定為從 Raspberry Pi 發佈 MQTT 訊息。

**Topics**
+ [建立組態檔](#iot-dc-install-dc-configure-step1)
+ [開啟 MQTT 測試用戶端](#iot-dc-install-dc-configure-step2)
+ [執行 AWS IoT 裝置用戶端](#iot-dc-install-dc-configure-step3)

## 建立組態檔
<a name="iot-dc-install-dc-configure-step1"></a>

此程序會建立組態檔案來測試 AWS IoT 裝置用戶端。

**建立組態檔案以測試 AWS IoT 裝置用戶端**
+ 在連接至 Raspberry Pi 本機主機電腦上的終端機視窗中：

  1. 輸入下列命令來建立組態檔的目錄，並設定目錄的許可：

     ```
     mkdir ~/dc-configs
     chmod 745 ~/dc-configs
     ```

  1. 開啟文字編輯器，例如 `nano`。

  1. 複製此 JSON 文件並將其貼入開啟的文字編輯器中。

     ```
     {
       "endpoint": "a3qEXAMPLEaffp-ats.iot.us-west-2.amazonaws.com",
       "cert": "~/certs/testconn/device.pem.crt",
       "key": "~/certs/testconn/private.pem.key",
       "root-ca": "~/certs/AmazonRootCA1.pem",
       "thing-name": "DevCliTestThing",
       "logging": {
         "enable-sdk-logging": true,
         "level": "DEBUG",
         "type": "STDOUT",
         "file": ""
       },
       "jobs": {
         "enabled": false,
         "handler-directory": ""
       },
       "tunneling": {
         "enabled": false
       },
       "device-defender": {
         "enabled": false,
         "interval": 300
       },
       "fleet-provisioning": {
         "enabled": false,
         "template-name": "",
         "template-parameters": "",
         "csr-file": "",
         "device-key": ""
       },
       "samples": {
         "pub-sub": {
           "enabled": true,
           "publish-topic": "test/dc/pubtopic",
           "publish-file": "",
           "subscribe-topic": "test/dc/subtopic",
           "subscribe-file": ""
         }
       },
       "config-shadow": {
         "enabled": false
       },
       "sample-shadow": {
         "enabled": false,
         "shadow-name": "",
         "shadow-input-file": "",
         "shadow-output-file": ""
       }
     }
     ```

  1. 將*端點*值取代為您 AWS 帳戶 在 中找到之 的裝置資料端點[在 中佈建您的裝置 AWS IoT Core](iot-dc-install-provision.md#iot-dc-install-dc-provision)。

  1. 將文字編輯器中的檔案儲存為 **\$1/dc-configs/dc-testconn-config.json**。

  1. 執行此命令來設定新組態檔的許可。

     ```
     chmod 644 ~/dc-configs/dc-testconn-config.json
     ```

儲存檔案之後，您就可以繼續進行 [開啟 MQTT 測試用戶端](#iot-dc-install-dc-configure-step2)。

## 開啟 MQTT 測試用戶端
<a name="iot-dc-install-dc-configure-step2"></a>

此程序會準備 AWS IoT 主控台中的 **MQTT 測試用戶端**，以訂閱 AWS IoT 裝置用戶端在執行時發佈的 MQTT 訊息。

**準備 **MQTT test client** (MQTT 測試用戶端) 來訂閱所有 MQTT 訊息**

1. 在 [AWS IoT 主控台](https://console.aws.amazon.com//iot/home#/test)的本機主機電腦上，選擇 **MQTT test client** (MQTT 測試用戶端)。

1. 在 **Subscribe to a topic** (訂閱主題) 索引標籤的 **Topic filter** (主題篩選條件) 中，輸入 **\$1** (單個井字符號)，然後選擇 **Subscribe** (訂閱)，即可訂閱每個 MQTT 主題。

1. 在 **Subscriptions** (訂閱) 標籤下方，請確認看到 **\$1** (單個井字符號)。

在繼續進行 [執行 AWS IoT 裝置用戶端](#iot-dc-install-dc-configure-step3) 時，請讓有 **MQTT test client** (MQTT 測試用戶端) 的視窗保持開啟。

## 執行 AWS IoT 裝置用戶端
<a name="iot-dc-install-dc-configure-step3"></a>

此程序會執行 AWS IoT Device Client，以便發佈 MQTT **測試用戶端接收和顯示的單一 MQTT** 訊息。

**從 AWS IoT 裝置用戶端傳送 MQTT 訊息**

1. 請確保這兩個連接到 Raspberry Pi 的終端機視窗和有 **MQTT test client** (MQTT 測試用戶端) 的視窗會在您執行此程序時顯示出來。

1. 在終端機視窗中，輸入這些命令，以使用在 中建立的組態檔案執行 AWS IoT 裝置用戶端[建立組態檔](#iot-dc-install-dc-configure-step1)。

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-testconn-config.json
   ```

   在終端機視窗中， AWS IoT 裝置用戶端會顯示資訊訊息，以及執行時發生的任何錯誤。

   如果終端機視窗中未顯示任何錯誤，請檢閱 **MQTT test client** (MQTT 測試用戶端)。

1. 在 **MQTT test client** (MQTT 測試用戶端) 的 Subscriptions (訂閱) 視窗中，請參閱傳送至 `test/dc/pubtopic` 訊息主題的 *Hello World\$1* 訊息。

1. 如果 AWS IoT 裝置用戶端未顯示錯誤，而且您在 **MQTT 測試用戶端**中看到 *Hello World！* 傳送至`test/dc/pubtopic`訊息，表示連線成功。

1. 在終端機視窗中，輸入 **^C**(Ctrl-C) 以停止 AWS IoT 裝置用戶端。

在您示範 AWS IoT 裝置用戶端在 Raspberry Pi 上正確執行且可與 通訊之後 AWS IoT，您可以繼續前往 [教學課程：示範與 AWS IoT 裝置用戶端的 MQTT 訊息通訊](iot-dc-testconn.md)。

# 教學課程：示範與 AWS IoT 裝置用戶端的 MQTT 訊息通訊
<a name="iot-dc-testconn"></a>

本教學課程示範 AWS IoT 裝置用戶端如何訂閱和發佈 MQTT 訊息，這些訊息常用於 IoT 解決方案。

**若要開始此教學課程：**
+ 將本機主機電腦和 Raspberry Pi 設定成[上一節](iot-dc-install-dc.md)中的使用方式。

  如果您在安裝 AWS IoT 裝置用戶端後儲存 microSD 卡映像，則可以搭配 Raspberry Pi 使用該映像的 microSD 卡。
+ 如果您之前已執行過此示範，請檢閱 [步驟 2：使用 AWS IoT 裝置用戶端建置示範 AWS 帳戶 後清除您的](iot-dc-cleanup.md#iot-dc-cleanup-cloud) 以刪除先前執行中建立的所有 AWS IoT 資源，以避免重複的資源錯誤。

此教學課程約需 45 分鐘方能完成。

**完成此主題時：**
+ 您將示範 IoT 裝置從 訂閱 MQTT 訊息 AWS IoT 以及向其發佈 MQTT 訊息的不同方式 AWS IoT。

**必要設備：**
+ [上一節](iot-dc-install-dc.md)中的本機開發和測試環境
+ [上一節](iot-dc-install-dc.md)中使用的 Raspberry Pi
+ [上一節](iot-dc-install-dc.md)中使用的 Raspberry Pi microSD 記憶卡

**Topics**
+ [準備 Raspberry Pi 以示範 MQTT 訊息通訊](iot-dc-testconn-provision.md)
+ [示範使用 AWS IoT 裝置用戶端發佈訊息](iot-dc-testconn-publish.md)
+ [示範使用 AWS IoT 裝置用戶端訂閱訊息](iot-dc-testconn-subscribe.md)

# 準備 Raspberry Pi 以示範 MQTT 訊息通訊
<a name="iot-dc-testconn-provision"></a>

此程序會在 Raspberry Pi 中 AWS IoT 和 中建立資源，以使用 AWS IoT 裝置用戶端示範 MQTT 訊息通訊。

**Topics**
+ [建立憑證檔案來示範 MQTT 通訊](#iot-dc-testconn-provision-certs)
+ [佈建裝置來示範 MQTT 通訊](#iot-dc-testconn-provision-aws)
+ [設定 AWS IoT Device Client 組態檔案和 MQTT 測試用戶端，以示範 MQTT 通訊](#iot-dc-testconn-provision-dc-config)

## 建立憑證檔案來示範 MQTT 通訊
<a name="iot-dc-testconn-provision-certs"></a>

此程序會建立此示範的裝置憑證檔案。

**為 Raspberry Pi 建立並下載裝置憑證檔案**



1. 在本機主機電腦的終端機視窗中輸入下列命令，為裝置建立裝置憑證檔案。

   ```
   mkdir ~/certs/pubsub
   aws iot create-keys-and-certificate \
   --set-as-active \
   --certificate-pem-outfile "~/certs/pubsub/device.pem.crt" \
   --public-key-outfile "~/certs/pubsub/public.pem.key" \
   --private-key-outfile "~/certs/pubsub/private.pem.key"
   ```

   此命令會傳回類似以下的回應。儲存 `certificateArn` 值，供之後使用。

   ```
   {
   "certificateArn": "arn:aws:iot:us-west-2:57EXAMPLE833:cert/76e7e4edb3e52f52334be2f387a06145b2aa4c7fcd810f3aea2d92abc227d269",
   "certificateId": "76e7e4edb3e52f5233EXAMPLE7a06145b2aa4c7fcd810f3aea2d92abc227d269",
   "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIDWTCCAkGgAwIBAgI_SHORTENED_FOR_EXAMPLE_Lgn4jfgtS\n-----END CERTIFICATE-----\n",
   "keyPair": {
       "PublicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BA_SHORTENED_FOR_EXAMPLE_ImwIDAQAB\n-----END PUBLIC KEY-----\n",
       "PrivateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQE_SHORTENED_FOR_EXAMPLE_T9RoDiukY\n-----END RSA PRIVATE KEY-----\n"
   }
   }
   ```

1. 輸入下列命令來設定憑證目錄及其檔案的許可。

   ```
   chmod 700 ~/certs/pubsub
   chmod 644 ~/certs/pubsub/*
   chmod 600 ~/certs/pubsub/private.pem.key
   ```

1. 執行此命令來檢閱憑證目錄和檔案的許可。

   ```
   ls -l ~/certs/pubsub
   ```

   命令的輸出應該與您在此處看到的相同，但檔案日期和時間會有所不同。

   ```
   -rw-r--r-- 1 pi pi 1220 Oct 28 13:02 device.pem.crt
   -rw------- 1 pi pi 1675 Oct 28 13:02 private.pem.key
   -rw-r--r-- 1 pi pi  451 Oct 28 13:02 public.pem.key
   ```

1. 輸入這些命令來建立記錄檔案的目錄。

   ```
   mkdir ~/.aws-iot-device-client
   mkdir ~/.aws-iot-device-client/log
   chmod 745 ~/.aws-iot-device-client/log
   echo " " > ~/.aws-iot-device-client/log/aws-iot-device-client.log
   echo " " > ~/.aws-iot-device-client/log/pubsub_rx_msgs.log
   chmod 600 ~/.aws-iot-device-client/log/*
   ```

## 佈建裝置來示範 MQTT 通訊
<a name="iot-dc-testconn-provision-aws"></a>

本節會建立在 中佈建 Raspberry Pi AWS IoT 的資源 AWS IoT。

**若要在 AWS IoT中佈建裝置：**

1. 在本機主機電腦的終端機視窗中輸入下列命令，取得 AWS 帳戶裝置資料端點的地址。

   ```
   aws iot describe-endpoint --endpoint-type IoT:Data-ATS
   ```

   自您依照上一個教學課程執行此命令後，端點值便未發生變更。此處再次執行命令是為了輕鬆找到資料端點值並將其貼入本教學課程中使用的組態檔。

   先前步驟的命令會傳回類似以下的回應：記錄 `endpointAddress` 值，供之後使用。

   ```
   {
   "endpointAddress": "a3qjEXAMPLEffp-ats.iot.us-west-2.amazonaws.com"
   }
   ```

1. 輸入此命令來為您的 Raspberry Pi 建立新的 AWS IoT 物件資源。

   ```
   aws iot create-thing --thing-name "PubSubTestThing"
   ```

   由於 AWS IoT 物件資源是您在雲端中裝置的*虛擬*表示法，因此我們可以在 中建立多個物件資源 AWS IoT ，以用於不同的用途。這些資源都可以由同一個實體 IoT 裝置使用，用以代表裝置的不同面向。

   這些教學課程一次只會使用一個物件資源來表示 Raspberry Pi。如此一來，在這些教學課程中，它們代表不同的示範，因此在您為示範建立 AWS IoT 資源之後，您可以返回並使用您專門為每個示範建立的資源重複示範。

   如果您的 AWS IoT 物件資源已建立，命令會傳回類似這樣的回應。

   ```
   {
   "thingName": "PubSubTestThing",
   "thingArn": "arn:aws:iot:us-west-2:57EXAMPLE833:thing/PubSubTestThing",
   "thingId": "8ea78707-32c3-4f8a-9232-14bEXAMPLEfd"
   }
   ```

1. 在終端機視窗中：

   1. 開啟文字編輯器，例如 `nano`。

   1. 複製此 JSON 文件並將其貼入開啟的文字編輯器中。  
****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Connect"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:client/PubSubTestThing"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Publish"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/test/dc/pubtopic"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Subscribe"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topicfilter/test/dc/subtopic"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Receive"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/test/dc/subtopic"
                  ]
              }
          ]
      }
      ```

   1. 在編輯器中，在政策文件的每個`Resource`區段中，將 *us-west-2：57EXAMPLE833* 取代為 AWS 區域、冒號字元 (：) 和 12 位數字 AWS 帳戶 。

   1. 將文字編輯器中的檔案儲存為 **\$1/policies/pubsub\$1test\$1thing\$1policy.json**。

1. 執行此命令以使用先前步驟中的政策文件來建立 AWS IoT 政策。

   ```
   aws iot create-policy \
   --policy-name "PubSubTestThingPolicy" \
   --policy-document "file://~/policies/pubsub_test_thing_policy.json"
   ```

   如果建立此政策，此命令會傳回類似以下的回應。

   ```
   {
                                       "policyName": "PubSubTestThingPolicy",
                                       "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/PubSubTestThingPolicy",
                                       "policyDocument": "{\n\"Version\": \"2012-10-17\",		 	 	 \n\"Statement\": [\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Connect\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:client/PubSubTestThing\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Publish\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/pubtopic\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Subscribe\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/subtopic\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Receive\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/*\"\n]\n}\n]\n}\n",
                                       "policyVersionId": "1"
                                       }
   ```

1. 執行此命令，將此政策連接至裝置憑證。使用之前在本節儲存的 `certificateArn` 值來取代 `certificateArn`

   ```
   aws iot attach-policy \
   --policy-name "PubSubTestThingPolicy" \
   --target "certificateArn"
   ```

   若成功，此命令不會傳回任何內容。

1. 執行此命令，將裝置憑證連接至 AWS IoT 物件資源。使用之前在本節儲存的 `certificateArn` 值來取代 `certificateArn`

   ```
   aws iot attach-thing-principal \
   --thing-name "PubSubTestThing" \
   --principal "certificateArn"
   ```

   若成功，此命令不會傳回任何內容。

成功在 中佈建裝置後 AWS IoT，您就可以繼續 [設定 AWS IoT Device Client 組態檔案和 MQTT 測試用戶端，以示範 MQTT 通訊](#iot-dc-testconn-provision-dc-config)。

## 設定 AWS IoT Device Client 組態檔案和 MQTT 測試用戶端，以示範 MQTT 通訊
<a name="iot-dc-testconn-provision-dc-config"></a>

此程序會建立組態檔案來測試 AWS IoT 裝置用戶端。

**建立組態檔案以測試 AWS IoT 裝置用戶端**

1. 在連接至 Raspberry Pi 本機主機電腦上的終端機視窗中：

   1. 開啟文字編輯器，例如 `nano`。

   1. 複製此 JSON 文件並將其貼入開啟的文字編輯器中。

      ```
      {
        "endpoint": "a3qEXAMPLEaffp-ats.iot.us-west-2.amazonaws.com",
        "cert": "~/certs/pubsub/device.pem.crt",
        "key": "~/certs/pubsub/private.pem.key",
        "root-ca": "~/certs/AmazonRootCA1.pem",
        "thing-name": "PubSubTestThing",
        "logging": {
          "enable-sdk-logging": true,
          "level": "DEBUG",
          "type": "STDOUT",
          "file": ""
        },
        "jobs": {
          "enabled": false,
          "handler-directory": ""
        },
        "tunneling": {
          "enabled": false
        },
        "device-defender": {
          "enabled": false,
          "interval": 300
        },
        "fleet-provisioning": {
          "enabled": false,
          "template-name": "",
          "template-parameters": "",
          "csr-file": "",
          "device-key": ""
        },
        "samples": {
          "pub-sub": {
            "enabled": true,
            "publish-topic": "test/dc/pubtopic",
            "publish-file": "",
            "subscribe-topic": "test/dc/subtopic",
            "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
          }
        },
        "config-shadow": {
          "enabled": false
        },
        "sample-shadow": {
          "enabled": false,
          "shadow-name": "",
          "shadow-input-file": "",
          "shadow-output-file": ""
        }
      }
      ```

   1. 將*端點*值取代為您 AWS 帳戶 在 中找到之 的裝置資料端點[在 中佈建您的裝置 AWS IoT Core](iot-dc-install-provision.md#iot-dc-install-dc-provision)。

   1. 將文字編輯器中的檔案儲存為 **\$1/dc-configs/dc-pubsub-config.json**。

   1. 執行此命令來設定新組態檔的許可。

      ```
      chmod 644 ~/dc-configs/dc-pubsub-config.json
      ```

1. 若要準備 **MQTT test client** (MQTT 測試用戶端) 來訂閱所有 MQTT 訊息：

   1. 在 [AWS IoT 主控台](https://console.aws.amazon.com//iot/home#/test)的本機主機電腦上，選擇 **MQTT test client** (MQTT 測試用戶端)。

   1. 在 **Subscribe to a topic** (訂閱主題) 索引標籤的 **Topic filter** (主題篩選條件) 中，輸入 **\$1** (單個井字符號)，然後選擇 **Subscribe** (訂閱)。

   1. 在 **Subscriptions** (訂閱) 標籤下方，請確認看到 **\$1** (單個井字符號)。

   在繼續進行此教學課程時，請讓有 **MQTT test client** (MQTT 測試用戶端) 的視窗保持開啟。

在儲存檔案並設定 **MQTT test client** (MQTT 測試用戶端)之後，您就可以繼續進行 [示範使用 AWS IoT 裝置用戶端發佈訊息](iot-dc-testconn-publish.md)。

# 示範使用 AWS IoT 裝置用戶端發佈訊息
<a name="iot-dc-testconn-publish"></a>

本節中的程序示範 AWS IoT 裝置用戶端如何傳送預設和自訂 MQTT 訊息。

在上一個步驟為這些練習建立的此政策中的政策陳述式，會授予 Raspberry Pi 執行這些動作的許可：
+ 

**`iot:Connect`**  
提供名為 的用戶端`PubSubTestThing`進行連線，也就是執行 AWS IoT 裝置用戶端的 Raspberry Pi。

  ```
      {
        "Effect": "Allow",
        "Action": [
          "iot:Connect"
        ],
        "Resource": [
          "arn:aws:iot:us-west-2:57EXAMPLE833:client/PubSubTestThing"
        ]
      }
  ```
+ 

**`iot:Publish`**  
授予 Raspberry Pi 許可來發佈擁有 `test/dc/pubtopic` MQTT 主題的訊息。

  ```
      {
        "Effect": "Allow",
        "Action": [
          "iot:Publish"
        ],
        "Resource": [
          "arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/pubtopic"
        ]
      }
  ```

  此 `iot:Publish` 動作會授予許可來發佈至資源陣列中列出的 MQTT 主題。這些訊息的*內容*不受政策陳述式的控制。

## 使用 AWS IoT 裝置用戶端發佈預設訊息
<a name="iot-dc-testconn-publish-default"></a>

此程序會執行 AWS IoT Device Client，以便發佈 MQTT **測試用戶端接收和顯示的單一預設 MQTT** 訊息。

**從 AWS IoT 裝置用戶端傳送預設 MQTT 訊息**

1. 請確保這兩個連接到 Raspberry Pi 的本機主機電腦終端機視窗和有 **MQTT test client** (MQTT 測試用戶端) 的視窗，會在您執行此程序時顯示出來。

1. 在終端機視窗中，輸入這些命令，以使用在 中建立的組態檔案執行 AWS IoT 裝置用戶端[建立組態檔](iot-dc-install-configure.md#iot-dc-install-dc-configure-step1)。

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-config.json
   ```

   在終端機視窗中， AWS IoT 裝置用戶端會顯示資訊訊息，以及執行時發生的任何錯誤。

   如果終端機視窗中未顯示任何錯誤，請檢閱 **MQTT test client** (MQTT 測試用戶端)。

1. 在 **MQTT test client** (MQTT 測試用戶端) 的 **Subscriptions** (訂閱) 視窗中，請參閱傳送至 `test/dc/pubtopic` 訊息主題的 *Hello World\$1* 訊息。

1. 如果 AWS IoT Device Client 未顯示錯誤，而且您在 **MQTT 測試用戶端**看到 *Hello World！* 傳送至`test/dc/pubtopic`訊息，表示連線成功。

1. 在終端機視窗中，輸入 **^C**(Ctrl-C) 以停止 AWS IoT 裝置用戶端。

在您示範 AWS IoT Device Client 已發佈預設 MQTT 訊息之後，您可以繼續前往 [使用 AWS IoT 裝置用戶端發佈自訂訊息](#iot-dc-testconn-publish-custom)。

## 使用 AWS IoT 裝置用戶端發佈自訂訊息
<a name="iot-dc-testconn-publish-custom"></a>

本節中的程序會建立自訂 MQTT 訊息，然後執行 AWS IoT 裝置用戶端，以便它發佈一次自訂 MQTT 訊息，供 **MQTT test client** (MQTT 測試用戶端) 接收和顯示。

### 為 AWS IoT 裝置用戶端建立自訂 MQTT 訊息
<a name="iot-dc-testconn-publish-custom-create"></a>

在連接至 Raspberry Pi 本機主機電腦上的終端機視窗中執行這些步驟。

**為 AWS IoT 要發佈的裝置用戶端建立自訂訊息**

1. 在終端機視窗中，開啟文字編輯器，例如 `nano`。

1. 在文字編輯器中複製並貼入以下 JSON 文件。這將是 AWS IoT 裝置用戶端發佈的 MQTT 訊息承載。

   ```
   {
     "temperature": 28,
     "humidity": 80,
     "barometer": 1013,
     "wind": {
       "velocity": 22,
       "bearing": 255
     }
   }
   ```

1. 將文字編輯器的內容儲存為 **\$1/messages/sample-ws-message.json**。

1. 輸入下列命令，為剛建立的訊息檔案設定許可。

   ```
   chmod 600 ~/messages/*
   ```

**為 AWS IoT 裝置用戶端建立組態檔案，以用來傳送自訂訊息**

1. 在終端機視窗中，在 等文字編輯器中`nano`，開啟現有的 AWS IoT Device Client 組態檔案：**\$1/dc-configs/dc-pubsub-config.json**。

1. 按如下所示編輯 `samples` 物件。無需變更此檔案的其他部分。

   ```
     "samples": {
       "pub-sub": {
         "enabled": true,
         "publish-topic": "test/dc/pubtopic",
         "publish-file": "~/messages/sample-ws-message.json",
         "subscribe-topic": "test/dc/subtopic",
         "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
   ```

1. 將文字編輯器的內容儲存為 **\$1/dc-configs/dc-pubsub-custom-config.json**。

1. 執行此命令來設定新組態檔的許可。

   ```
   chmod 644 ~/dc-configs/dc-pubsub-custom-config.json
   ```

### 使用 AWS IoT 裝置用戶端發佈自訂 MQTT 訊息
<a name="iot-dc-testconn-publish-custom-publish"></a>

此項變更只會影響 MQTT 訊息承載的*內容*，因此目前的政策會繼續運作。不過，如果 *MQTT 主題* (如 `~/dc-configs/dc-pubsub-custom-config.json` 中定義的 `publish-topic` 值) 已變更，`iot::Publish` 政策陳述式也需要進行修改，以允許 Raspberry Pi 發佈至新的 MQTT 主題。

**從 AWS IoT 裝置用戶端傳送 MQTT 訊息**

1. 請確保這兩個終端機視窗和有 **MQTT test client** (MQTT 測試用戶端) 的視窗，會在您執行此程序時顯示出來。此外，請確保 **MQTT test client** (MQTT 測試用戶端) 仍然訂閱了 **\$1** 主題篩選條件。如果未訂閱，請訂閱 **\$1** 主題篩選條件。

1. 在終端機視窗中輸入這些命令，使用在 [建立組態檔](iot-dc-install-configure.md#iot-dc-install-dc-configure-step1) 中建立的組態檔來執行 AWS IoT 裝置用戶端。

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-custom-config.json
   ```

   在終端機視窗中， AWS IoT 裝置用戶端會顯示資訊訊息，以及執行時發生的任何錯誤。

   如果終端機視窗中未顯示任何錯誤，請檢閱 MQTT test client (MQTT 測試用戶端)。

1. 在 **MQTT test client** (MQTT 測試用戶端) 的 **Subscriptions** (訂閱) 視窗中，參閱傳送至 `test/dc/pubtopic` 訊息主題的自訂訊息承載。

1. 如果 AWS IoT Device Client 沒有顯示錯誤，而且您在 **MQTT 測試用戶端**中看到發佈至`test/dc/pubtopic`訊息的自訂訊息承載，表示您已成功發佈自訂訊息。

1. 在終端機視窗中，輸入 **^C**(Ctrl-C) 以停止 AWS IoT 裝置用戶端。

在您示範 AWS IoT Device Client 已發佈自訂訊息承載之後，您可以繼續 [示範使用 AWS IoT 裝置用戶端訂閱訊息](iot-dc-testconn-subscribe.md)。

# 示範使用 AWS IoT 裝置用戶端訂閱訊息
<a name="iot-dc-testconn-subscribe"></a>

在本節中，您會示範兩種類型的訊息訂閱：
+ 單一主題訂閱
+ 萬用字元主題訂閱

為這些練習建立的此政策中的政策陳述式會授予 Raspberry Pi 執行這些動作的許可：
+ 

**`iot:Receive`**  
授予 AWS IoT Device Client 許可，以接收符合`Resource`物件中名為 的 MQTT 主題。

  ```
      {
        "Effect": "Allow",
        "Action": [
          "iot:Receive"
        ],
        "Resource": [
          "arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/subtopic"
        ]
      }
  ```
+ 

**`iot:Subscribe`**  
授予 AWS IoT Device Client 許可，以訂閱符合`Resource`物件中名為 的 MQTT 主題篩選條件。

  ```
      {
        "Effect": "Allow",
        "Action": [
          "iot:Subscribe"
        ],
        "Resource": [
          "arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/subtopic"
        ]
      }
  ```

## 訂閱單一 MQTT 訊息主題
<a name="iot-dc-testconn-subscribe-simple-topic"></a>

此程序示範 AWS IoT 裝置用戶端如何訂閱和記錄 MQTT 訊息。

在連接至 Raspberry Pi 本機主機電腦上的終端機視窗中，列出 **\$1/dc-configs/dc-pubsub-custom-config.json** 的內容或在文字編輯器中開啟檔案來檢閱其內容。找到 `samples` 物件，它應該如下所示。

```
  "samples": {
    "pub-sub": {
      "enabled": true,
      "publish-topic": "test/dc/pubtopic",
      "publish-file": "~/messages/sample-ws-message.json",
      "subscribe-topic": "test/dc/subtopic",
      "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
```

請注意 `subscribe-topic` 值是 MQTT 主題， AWS IoT 裝置用戶端會在執行時訂閱該主題。 AWS IoT Device Client 會將從此訂閱收到的訊息承載寫入 `subscribe-file`值中名為 的檔案。

**從 AWS IoT 裝置用戶端訂閱 MQTT 訊息主題**

1. 請確保這兩個終端機視窗和有 MQTT test client (MQTT 測試用戶端) 的視窗，會在您執行此程序時顯示出來。此外，請確保 **MQTT test client** (MQTT 測試用戶端) 仍然訂閱了 **\$1** 主題篩選條件。如果未訂閱，請訂閱 **\$1** 主題篩選條件。

1. 在終端機視窗中，輸入這些命令，以使用在 中建立的組態檔案執行 AWS IoT 裝置用戶端[建立組態檔](iot-dc-install-configure.md#iot-dc-install-dc-configure-step1)。

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-custom-config.json
   ```

   在終端機視窗中， AWS IoT 裝置用戶端會顯示資訊訊息，以及執行時發生的任何錯誤。

   如果終端機視窗中未顯示任何錯誤，請在 AWS IoT 主控台中繼續進行。

1. 在 AWS IoT 主控台的 **MQTT 測試用戶端**中，選擇**發佈至主題**索引標籤。

1. 在 **Topic name** (主題名稱) 中輸入 **test/dc/subtopic**。

1. 在 **Message payload** (訊息承載) 中，檢閱郵件內容。

1. 請選擇 **Publish** (發佈) 來發佈 MQTT 訊息。

1. 在終端機視窗中，請留意從 AWS IoT Device Client *接收的訊息*項目，如下所示。

   ```
   2021-11-10T16:02:20.890Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 45 bytes
   ```

1. 在您看到顯示訊息已接收*的訊息*項目後，請輸入 **^C**(Ctrl-C) 以停止 AWS IoT 裝置用戶端。

1. 輸入此命令來檢視訊息日誌檔案的結尾，查看您從 **MQTT test client** (MQTT 測試用戶端) 發佈的訊息。

   ```
   tail ~/.aws-iot-device-client/log/pubsub_rx_msgs.log
   ```

藉由檢視日誌檔案中的訊息，您示範了 AWS IoT 裝置用戶端收到您從 MQTT 測試用戶端發佈的訊息。

## 使用萬用字元訂閱多個 MQTT 訊息主題
<a name="iot-dc-testconn-subscribe-wild-topic"></a>

這些程序示範 AWS IoT 裝置用戶端如何使用萬用字元訂閱和記錄 MQTT 訊息。若要做到這一點，您必須：

1. 更新 AWS IoT Device Client 用來訂閱 MQTT 主題的主題篩選條件。

1. 更新裝置所使用的政策，以允許新的訂閱。

1. 執行 AWS IoT 裝置用戶端，並從 MQTT 測試主控台發佈訊息。

**使用萬用字元 MQTT 主題篩選條件建立用於訂閱多個 MQTT 訊息主題的組態檔**

1. 在連接至 Raspberry Pi 本機主機電腦的終端機視窗中，開啟 **\$1/dc-configs/dc-pubsub-custom-config.json** 進行編輯，並找出 `samples` 物件。

1. 在文字編輯器中，找出 `samples` 物件並更新 `subscribe-topic` 值，如下所示。

   ```
     "samples": {
       "pub-sub": {
         "enabled": true,
         "publish-topic": "test/dc/pubtopic",
         "publish-file": "~/messages/sample-ws-message.json",
         "subscribe-topic": "test/dc/#",
         "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
   ```

   新 `subscribe-topic` 值是末尾具有 MQTT 萬用字元的 [MQTT 主題篩選條件](topics.md#topicfilters)。本節說明訂閱所有以 `test/dc/` 為開頭的 MQTT 主題。 AWS IoT Device Client 會將從此訂閱收到的訊息承載寫入 中名為 的檔案`subscribe-file`。

1. 將修改的組態檔儲存為 **\$1/dc-configs/dc-pubsub-wild-config.json**，然後退出編輯器。

**修改 Raspberry Pi 使用的政策，以允許訂閱和接收多個 MQTT 消息主題**

1. 在連接至 Raspberry Pi 的本機主機電腦上的終端機視窗中，於最喜歡的文字編輯器中開啟 **\$1/policies/pubsub\$1test\$1thing\$1policy.json** 進行編輯，然後找出檔案中的 `iot::Subscribe` 和 `iot::Receive` 政策陳述式。

1. 在 `iot::Subscribe` 政策陳述式中，更新資源物件中的字串，用 `*` 取代 `subtopic`，使其如下所示。

   ```
       {
         "Effect": "Allow",
         "Action": [
           "iot:Subscribe"
         ],
         "Resource": [
           "arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/*"
         ]
       }
   ```
**注意**  
此 [MQTT 主題篩選條件萬用字元](topics.md#topicfilters) 是 `+` (加號) 和 `#` (井號)。結尾帶有 `#` 的訂閱請求會訂閱所有以 `#` 字元前面的字串為開頭的主題 (例如本例中的 `test/dc/`)。  
不過，政策陳述式中授權此訂閱的資源值必須在主題篩選條件 ARN 中使用 `*` (星號) 取代 `#` (井號)。這是因為政策處理器使用的萬用字元與 MQTT 使用的不同。  
如需有關在政策中為主題和主題篩選條件使用萬用字元的詳細資訊，請參閱 [在 MQTT 和 AWS IoT Core 政策中使用萬用字元](pub-sub-policy.md#pub-sub-policy-cert)。

1. 在 `iot::Receive` 政策陳述式中，更新資源物件中的字串，用 `*` 取代 `subtopic`，使其如下所示。

   ```
       {
         "Effect": "Allow",
         "Action": [
           "iot:Receive"
         ],
         "Resource": [
           "arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/*"
         ]
       }
   ```

1. 將更新後的政策文件儲存為 **\$1/policies/pubsub\$1wild\$1test\$1thing\$1policy.json**，然後退出編輯器。

1. 輸入此指令來更新此教學課程的政策，以使用新的資源定義。

   ```
   aws iot create-policy-version \
   --set-as-default \
   --policy-name "PubSubTestThingPolicy" \
   --policy-document "file://~/policies/pubsub_wild_test_thing_policy.json"
   ```

   如果命令成功，它會傳回類似這樣的回應。請注意，`policyVersionId` 現在是 `2`，表示這是此政策的第二個版本。

   如果成功更新了政策，您可以繼續進行下一個程序。

   ```
   {
       "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/PubSubTestThingPolicy",
       "policyDocument": "{\n  \"Version\": \"2012-10-17\",		 	 	 \n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iot:Connect\"\n      ],\n      \"Resource\": [\n        \"arn:aws:iot:us-west-2:57EXAMPLE833:client/PubSubTestThing\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iot:Publish\"\n      ],\n      \"Resource\": [\n        \"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/pubtopic\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iot:Subscribe\"\n      ],\n      \"Resource\": [\n        \"arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iot:Receive\"\n      ],\n      \"Resource\": [\n        \"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/*\"\n      ]\n    }\n  ]\n}\n",
       "policyVersionId": "2",
       "isDefaultVersion": true
   }
   ```

   如果收到因政策版本過多而無法儲存新政策的錯誤，請輸入此命令來列出政策的目前版本。檢閱此命令傳回的清單，找出可以刪除的政策版本。

   ```
   aws iot list-policy-versions --policy-name "PubSubTestThingPolicy"
   ```

   輸入此命令來刪除不再需要的版本。請注意，您無法刪除預設政策版本。預設政策版本的 `isDefaultVersion` 值為 `true`。

   ```
   aws iot delete-policy-version \
   --policy-name "PubSubTestThingPolicy" \
   --policy-version-id policyId
   ```

   刪除政策版本後，請重試此步驟。

使用更新的組態檔案和政策，您就可以使用 AWS IoT 裝置用戶端示範萬用字元訂閱。

**示範 AWS IoT 裝置用戶端如何訂閱和接收多個 MQTT 訊息主題**

1. 在 **MQTT test client** (MQTT 測試用戶端) 中，檢查訂閱。如果 **MQTT test client** (MQTT 測試用戶端) 訂閱了 **\$1** 主題篩選條件，請繼續下一個步驟。如果沒有，進入 **MQTT test client** (MQTT 測試用戶端)，在 **Subscribe to a topic** (訂閱主題) 索引標籤的 **Topic filter** (主題篩選條件) 中，輸入 **\$1** (井號字元)，然後選擇 **Subscribe** (訂閱) 進行訂閱。

1. 在連接至 Raspberry Pi 的本機主機電腦終端機視窗中，輸入這些命令來啟動 AWS IoT 裝置用戶端。

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-wild-config.json
   ```

1. 在本機主機電腦上的終端機視窗中觀看 AWS IoT Device Client 輸出時，請返回 **MQTT 測試用戶端**。在 **Publish to a topic** (發佈至主題) 索引標籤中的 **Topic name** (主題名稱) 輸入 **test/dc/subtopic**，然後選擇 **Publish** (發佈)。

1. 在終端機視窗中，尋找如下訊息來確認已收到訊息：

   ```
   2021-11-10T16:34:20.101Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 76 bytes
   ```

1. 在本機主機電腦的終端機視窗中觀看 AWS IoT Device Client 輸出時，請返回 **MQTT 測試用戶端**。在 **Publish to a topic** (發佈至主題) 索引標籤中的 **Topic name** (主題名稱) 輸入 **test/dc/subtopic2**，然後選擇 **Publish** (發佈)。

1. 在終端機視窗中，尋找如下訊息來確認已收到訊息：

   ```
   2021-11-10T16:34:32.078Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 77 bytes
   ```

1. 在您看到確認收到兩個訊息的訊息後，請輸入 **^C**(Ctrl-C) 以停止 AWS IoT 裝置用戶端。

1. 輸入此命令來檢視訊息日誌檔案的結尾，查看您從 **MQTT test client** (MQTT 測試用戶端) 發佈的訊息。

   ```
   tail -n 20 ~/.aws-iot-device-client/log/pubsub_rx_msgs.log
   ```
**注意**  
記錄檔案僅包含訊息承載。訊息主題不會記錄在接收到的訊息日誌檔案中。  
您也可以在收到的日誌中看到 AWS IoT 裝置用戶端發佈的訊息。這是因為萬用字元主題篩選條件會包含該訊息主題，有時候，訂閱請求可能由訊息代理程式處理，然後才將發佈的訊息傳送給訂閱者。

日誌檔案中的項目會示範已收到訊息。您可以使用其他主題名稱重複此程序。所有主題名稱以 `test/dc/` 為開頭的訊息應該會被接收並記錄。主題名稱以任何其他文字為開頭的訊息都會被忽略。

在示範 AWS IoT 裝置用戶端如何發佈和訂閱 MQTT 訊息之後，請繼續 [教學課程：使用 AWS IoT 裝置用戶端示範遠端動作 （任務）](iot-dc-runjobs.md)。

# 教學課程：使用 AWS IoT 裝置用戶端示範遠端動作 （任務）
<a name="iot-dc-runjobs"></a>

在這些教學課程中，您要設定並部署任務至 Raspberry Pi，以此示範如何將遠程操作發送至 IoT 裝置。

**若要開始此教學課程：**
+ 將本機主機電腦和 Raspberry Pi 設定成[上一節](iot-dc-testconn.md)中的使用方式。
+ 如果您尚未完成上一節中的教學課程，您可以使用 Raspberry Pi 搭配 microSD 卡來嘗試本教學課程，該卡具有您在 中安裝 AWS IoT 裝置用戶端後儲存的影像[(選用) 儲存 microSD 卡映像](iot-dc-install-download.md#iot-dc-install-dc-save)。
+ 如果您之前已執行過此示範，請檢閱 [步驟 2：使用 AWS IoT 裝置用戶端建置示範 AWS 帳戶 後清除您的](iot-dc-cleanup.md#iot-dc-cleanup-cloud) 以刪除先前執行中建立的所有 AWS IoT 資源，以避免重複的資源錯誤。

此教學課程約需 45 分鐘方能完成。

**完成此主題時：**
+ 您將展示 IoT 裝置可以使用 AWS IoT Core 執行 管理之遠端操作的不同方式 AWS IoT 。

**必要設備：**
+ [上一節](iot-dc-install-dc.md)中測試的本機開發和測試環境
+ [上一節](iot-dc-install-dc.md)中測試的 Raspberry Pi
+ [上一節](iot-dc-install-dc.md)中測試的 Raspberry Pi microSD 記憶卡

**Topics**
+ [準備 Raspberry Pi 以執行任務](iot-dc-runjobs-prepare.md)
+ [AWS IoT 使用 AWS IoT 裝置用戶端在 中建立和執行任務](iot-dc-runjobs-prepare-define.md)

# 準備 Raspberry Pi 以執行任務
<a name="iot-dc-runjobs-prepare"></a>

本節中的程序說明如何使用 AWS IoT 裝置用戶端，讓您的 Raspberry Pi 準備好執行任務。

**注意**  
這些程序是裝置特定的程序。如果想要同時使用多個裝置執行本節中的程序，每個裝置都需要有自己的政策和唯一的裝置特定憑證及物件名稱。若要為每個裝置提供獨特資源，請在按程序所述變更裝置特定元素時，針對每個裝置執行此程序一次。

**Topics**
+ [佈建 Raspberry Pi 來示範任務](#iot-dc-runjobs-prepare-provision)
+ [設定 AWS IoT 裝置用戶端以執行任務代理程式](#iot-dc-runjobs-prepare-config)

## 佈建 Raspberry Pi 來示範任務
<a name="iot-dc-runjobs-prepare-provision"></a>

本節中的程序 AWS IoT 會透過為 Raspberry Pi 建立 AWS IoT 資源和裝置憑證，在 中佈建您的 Raspberry Pi。

**Topics**
+ [建立和下載裝置憑證檔案以示範 AWS IoT 任務](#iot-dc-runjobs-prepare-cert)
+ [建立 AWS IoT 資源以示範 AWS IoT 任務](#iot-dc-runjobs-prepare-iot)

### 建立和下載裝置憑證檔案以示範 AWS IoT 任務
<a name="iot-dc-runjobs-prepare-cert"></a>

此程序會建立此示範的裝置憑證檔案。

如果要準備一個以上的裝置，則必須在每個裝置上執行此程序。

**若要為 Raspberry Pi 建立並下載裝置憑證檔案：**

在連接至 Raspberry Pi 的本機主機電腦終端機視窗中，輸入這些命令。

1. 請輸入下列命令，為裝置建立裝置憑證檔案。

   ```
   aws iot create-keys-and-certificate \
   --set-as-active \
   --certificate-pem-outfile "~/certs/jobs/device.pem.crt" \
   --public-key-outfile "~/certs/jobs/public.pem.key" \
   --private-key-outfile "~/certs/jobs/private.pem.key"
   ```

   此命令會傳回類似以下的回應。儲存 `certificateArn` 值，供之後使用。

   ```
   {
   "certificateArn": "arn:aws:iot:us-west-2:57EXAMPLE833:cert/76e7e4edb3e52f52334be2f387a06145b2aa4c7fcd810f3aea2d92abc227d269",
   "certificateId": "76e7e4edb3e52f5233EXAMPLE7a06145b2aa4c7fcd810f3aea2d92abc227d269",
   "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIDWTCCAkGgAwIBAgI_SHORTENED_FOR_EXAMPLE_Lgn4jfgtS\n-----END CERTIFICATE-----\n",
   "keyPair": {
       "PublicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BA_SHORTENED_FOR_EXAMPLE_ImwIDAQAB\n-----END PUBLIC KEY-----\n",
       "PrivateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQE_SHORTENED_FOR_EXAMPLE_T9RoDiukY\n-----END RSA PRIVATE KEY-----\n"
   }
   }
   ```

1. 輸入下列命令來設定憑證目錄及其檔案的許可。

   ```
   chmod 700 ~/certs/jobs
   chmod 644 ~/certs/jobs/*
   chmod 600 ~/certs/jobs/private.pem.key
   ```

1. 執行此命令來檢閱憑證目錄和檔案的許可。

   ```
   ls -l ~/certs/jobs
   ```

   命令的輸出應該與您在此處看到的相同，但檔案日期和時間會有所不同。

   ```
   -rw-r--r-- 1 pi pi 1220 Oct 28 13:02 device.pem.crt
   -rw------- 1 pi pi 1675 Oct 28 13:02 private.pem.key
   -rw-r--r-- 1 pi pi  451 Oct 28 13:02 public.pem.key
   ```

在下載裝置憑證檔案至 Raspberry Pi 之後，您就可以繼續進行 [佈建 Raspberry Pi 來示範任務](#iot-dc-runjobs-prepare-provision)。

### 建立 AWS IoT 資源以示範 AWS IoT 任務
<a name="iot-dc-runjobs-prepare-iot"></a>

建立此裝置 AWS IoT 的資源。

如果要準備一個以上的裝置，則必須為每個裝置上執行此程序。



**若要在 AWS IoT中佈建裝置：**

在連接至 Raspberry Pi 本機主機電腦上的終端機視窗中：

1. 輸入下列命令，取得 AWS 帳戶裝置資料端點地址。

   ```
   aws iot describe-endpoint --endpoint-type IoT:Data-ATS
   ```

   自您上一次執行此命令後，端點值便未發生變更。此處再次執行命令是為了輕鬆找出資料端點值並貼入本教學課程中使用的組態檔。

   **describe-endpoint** 命令會傳回類似以下的回應。記錄 `endpointAddress` 值，供之後使用。

   ```
   {
   "endpointAddress": "a3qjEXAMPLEffp-ats.iot.us-west-2.amazonaws.com"
   }
   ```

1. 使用裝置的唯一名稱來取代 *uniqueThingName*。如果想要使用多個裝置執行本教學課程，請賦予每個裝置自己的名稱。例如 **TestDevice01**、**TestDevice02** 等等。

   輸入此命令來為您的 Raspberry Pi 建立新的 AWS IoT 物件資源。

   ```
   aws iot create-thing --thing-name "uniqueThingName"
   ```

   由於 AWS IoT 物件資源是雲端中裝置的*虛擬*表示法，因此我們可以在 中建立多個物件資源 AWS IoT ，以用於不同的用途。這些資源都可以由同一個實體 IoT 裝置使用，用以代表裝置的不同面向。
**注意**  
當您想要保護多個裝置的政策時，可以使用 `${iot:Thing.ThingName}` 來取代靜態物件名稱 `uniqueThingName`。

   這些教學課程每次只會使用一個物件資源。如此一來，在這些教學課程中，它們代表不同的示範，因此在您為示範建立 AWS IoT 資源之後，您可以使用您專門為每個示範建立的資源來返回並重複示範。

   如果您的 AWS IoT 物件資源已建立，命令會傳回類似這樣的回應。記錄 `thingArn` 值以供稍後在此裝置上建立要執行的任務時使用。

   ```
   {
   "thingName": "uniqueThingName",
   "thingArn": "arn:aws:iot:us-west-2:57EXAMPLE833:thing/uniqueThingName",
   "thingId": "8ea78707-32c3-4f8a-9232-14bEXAMPLEfd"
   }
   ```

1. 在終端機視窗中：

   1. 開啟文字編輯器，例如 `nano`。

   1. 複製此 JSON 文件並將其貼入開啟的文字編輯器中。  
****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Connect"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:client/uniqueThingName"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Publish"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/test/dc/pubtopic",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/events/job/*",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/events/jobExecution/*",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/things/uniqueThingName/jobs/*"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Subscribe"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topicfilter/test/dc/subtopic",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/events/jobExecution/*",
                      "arn:aws:iot:us-west-2:123456789012:topicfilter/$aws/things/uniqueThingName/jobs/*"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Receive"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/test/dc/subtopic",
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/things/uniqueThingName/jobs/*"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:DescribeJobExecution",
                      "iot:GetPendingJobExecutions",
                      "iot:StartNextPendingJobExecution",
                      "iot:UpdateJobExecution"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-west-2:123456789012:topic/$aws/things/uniqueThingName"
                  ]
              }
          ]
      }
      ```

   1. 在編輯器的每個政策陳述式 `Resource` 區段中，使用 AWS 區域來取代 *us-west-2:57EXAMPLE833*、一個冒號字元 (:) 和 12 位數的 AWS 帳戶 編號。

   1. 在編輯器的在每個政策陳述式中，使用您賦予此物件資源的物件名稱來取代 *uniqueThingName*。

   1. 將文字編輯器中的檔案儲存為 **\$1/policies/jobs\$1test\$1thing\$1policy.json**。

      如果為多個裝置執行此程序，請在每個裝置上將檔案儲存為此檔案名稱。

1. 將 *uniqueThingName* 取代為裝置的物件名稱，然後執行此命令來建立為該裝置量身打造 AWS IoT 的政策。

   ```
   aws iot create-policy \
   --policy-name "JobTestPolicyForuniqueThingName" \
   --policy-document "file://~/policies/jobs_test_thing_policy.json"
   ```

   如果建立此政策，此命令會傳回類似以下的回應。  
****  

   ```
   {
       "policyName": "JobTestPolicyForuniqueThingName",
       "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/JobTestPolicyForuniqueThingName",
       "policyDocument": "{\n\"Version\": \"2012-10-17\",\n\"Statement\": [\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Connect\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:client/PubSubTestThing\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Publish\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/pubtopic\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Subscribe\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topicfilter/test/dc/subtopic\"\n]\n},\n{\n\"Effect\": \"Allow\",\n\"Action\": [\n\"iot:Receive\"\n],\n\"Resource\": [\n\"arn:aws:iot:us-west-2:57EXAMPLE833:topic/test/dc/*\"\n]\n}\n]\n}\n",
       "policyVersionId": "1"
   }
   ```

1. 使用裝置的物件名稱來取代 *uniqueThingName*，再使用稍早您在本節為此裝置儲存的 `certificateArn` 值來取代 `certificateArn`，然後執行此命令來將政策連接至裝置憑證。

   ```
   aws iot attach-policy \
   --policy-name "JobTestPolicyForuniqueThingName" \
   --target "certificateArn"
   ```

   若成功，此命令不會傳回任何內容。

1.  將 *uniqueThingName* 取代為裝置的物件名稱，將 取代`certificateArn`為您稍早在本節中儲存`certificateArn`的值，然後執行此命令以將裝置憑證連接至 AWS IoT 物件資源。

   ```
   aws iot attach-thing-principal \
   --thing-name "uniqueThingName" \
   --principal "certificateArn"
   ```

   若成功，此命令不會傳回任何內容。

在成功佈建 Raspberry Pi 之後，您就可以在測試中為另一 Raspberry Pi 重複本節程序；或者，如果所有裝置都已佈建，則繼續進行 [設定 AWS IoT 裝置用戶端以執行任務代理程式](#iot-dc-runjobs-prepare-config)。

## 設定 AWS IoT 裝置用戶端以執行任務代理程式
<a name="iot-dc-runjobs-prepare-config"></a>

此程序會為 AWS IoT 裝置用戶端建立組態檔案，以執行任務代理程式：。

注意：如果要準備一個以上的裝置，則必須在每個裝置上執行此程序。

**若要建立組態檔案以測試 AWS IoT 裝置用戶端：**

1. 在連接至 Raspberry Pi 本機主機電腦上的終端機視窗中：

   1. 開啟文字編輯器，例如 `nano`。

   1. 複製此 JSON 文件並將其貼入開啟的文字編輯器中。

      ```
      {
        "endpoint": "a3qEXAMPLEaffp-ats.iot.us-west-2.amazonaws.com",
        "cert": "~/certs/jobs/device.pem.crt",
        "key": "~/certs/jobs/private.pem.key",
        "root-ca": "~/certs/AmazonRootCA1.pem",
        "thing-name": "uniqueThingName",
        "logging": {
          "enable-sdk-logging": true,
          "level": "DEBUG",
          "type": "STDOUT",
          "file": ""
        },
        "jobs": {
          "enabled": true,
          "handler-directory": ""
        },
        "tunneling": {
          "enabled": false
        },
        "device-defender": {
          "enabled": false,
          "interval": 300
        },
        "fleet-provisioning": {
          "enabled": false,
          "template-name": "",
          "template-parameters": "",
          "csr-file": "",
          "device-key": ""
        },
        "samples": {
          "pub-sub": {
            "enabled": false,
            "publish-topic": "",
            "publish-file": "",
            "subscribe-topic": "",
            "subscribe-file": ""
          }
        },
        "config-shadow": {
          "enabled": false
        },
        "sample-shadow": {
          "enabled": false,
          "shadow-name": "",
          "shadow-input-file": "",
          "shadow-output-file": ""
        }
      }
      ```

   1. 將*端點*值取代為您 AWS 帳戶 在 中找到之 的裝置資料端點值[在 中佈建您的裝置 AWS IoT Core](iot-dc-install-provision.md#iot-dc-install-dc-provision)。

   1. 用此裝置使用的物件名稱取代 *uniqueThingName*。

   1. 將文字編輯器中的檔案儲存為 **\$1/dc-configs/dc-jobs-config.json**。

1. 執行此命令來設定新組態檔的檔案許可。

   ```
   chmod 644 ~/dc-configs/dc-jobs-config.json
   ```

您不必使用 **MQTT test client** (MQTT 測試用戶端) 進行此測試。雖然裝置將與 交換任務相關的 MQTT 訊息 AWS IoT，但任務進度訊息只會與執行任務的裝置交換。由於任務進度訊息只會與執行任務的裝置交換，因此您無法從其他裝置訂閱這些訊息，例如 AWS IoT 主控台。

儲存組態檔之後，您就可以繼續進行 [AWS IoT 使用 AWS IoT 裝置用戶端在 中建立和執行任務](iot-dc-runjobs-prepare-define.md)。

# AWS IoT 使用 AWS IoT 裝置用戶端在 中建立和執行任務
<a name="iot-dc-runjobs-prepare-define"></a>

本節中的程序會建立任務文件和 AWS IoT 任務資源。建立任務資源後， 會將任務文件 AWS IoT 傳送至任務代理程式將任務文件套用至裝置或用戶端的指定任務目標。

**Topics**
+ [建立和存放 IoT 任務的任務文件](#iot-dc-runjobs-prepare-define-jobdoc)
+ [AWS IoT 在一個 IoT 裝置的 中執行任務](#iot-dc-runjobs-prepare-define-job)

## 建立和存放 IoT 任務的任務文件
<a name="iot-dc-runjobs-prepare-define-jobdoc"></a>

此程序會建立簡單的任務文件，以包含在 AWS IoT 任務資源中。此任務文件會在任務目標上 顯示 "Hello world\$1"。

**若要建立和儲存任務文件：**

1. 選取要儲存任務文件的 Amazon S3 儲存貯體。如果沒有可使用的現有 Amazon S3 儲存貯體，就需要建立一個。如需如何建立 Amazon S3 儲存貯體的詳細資訊，請參閱 [Amazon S3 入門](https://docs.aws.amazon.com//AmazonS3/latest/userguide/GetStartedWithS3.html)中的主題。

1. 建立並儲存此任務的任務文件

   1. 在本機主機電腦上，開啟文字編輯器。

   1. 將此文字複製並貼入編輯器中。

      ```
      {
          "operation": "echo",
          "args": ["Hello world!"]
      }
      ```

   1. 在本機主機電腦上，將編輯器的內容儲存至名為 **hello-world-job.json** 的檔案。

   1. 請確認檔案已正確儲存。某些文字編輯器會在儲存文字檔案時自動附加 `.txt` 至檔案名稱。如果編輯器附加了 `.txt` 至檔案名稱，請更正檔案名稱後再繼續。

1. 使用 **hello-world-job.json** 路徑來取代 *path\$1to\$1file*；如果該路徑不在當前目錄中，則使用所選儲存貯體的 Amazon S3 儲存貯體路徑取代 *s3\$1bucket\$1name*，然後執行此命令將任務文件放入 Amazon S3 儲存貯體中。

   ```
   aws s3api put-object \
   --key hello-world-job.json \
   --body path_to_file/hello-world-job.json --bucket s3_bucket_name
   ```

   識別儲存在 Amazon S3 中的任務文件的任務文件 URL 是透過取代以下 URL 中 *s3\$1bucket\$1name* 和 *AWS\$1region* 來決定。記錄產生的 URL 以便稍後使用為 *job\$1document\$1path*

   ```
   https://s3_bucket_name.s3.AWS_Region.amazonaws.com/hello-world-job.json
   ```
**注意**  
AWS 安全性可防止您在 外部開啟此 URL AWS 帳戶，例如使用瀏覽器。根據預設，具有 檔案存取權 AWS IoT 的任務引擎會使用 URL。在生產環境中，您需要確保 AWS IoT 服務具有存取儲存在 Amazon S3 中任務文件的許可。

在儲存任務文件的 URL 之後，請繼續進行 [AWS IoT 在一個 IoT 裝置的 中執行任務](#iot-dc-runjobs-prepare-define-job)。

## AWS IoT 在一個 IoT 裝置的 中執行任務
<a name="iot-dc-runjobs-prepare-define-job"></a>

本節中的程序會啟動 Raspberry Pi 上的 AWS IoT Device Client，以在裝置上執行任務代理程式，以等待任務執行。它也會在 中建立任務資源 AWS IoT，將任務傳送至 IoT 裝置並在其上執行。

**注意**  
此程序只會在單一裝置上執行任務。

**若要啟動 Raspberry Pi 任務代理程式：**

1. 在本機主機電腦上連線至 Raspberry Pi 的終端機視窗中，執行此命令來啟動 AWS IoT 裝置用戶端。

   ```
   cd ~/aws-iot-device-client/build
   ./aws-iot-device-client --config-file ~/dc-configs/dc-jobs-config.json
   ```

1. 在終端機視窗中，確認 AWS IoT 裝置用戶端並顯示這些訊息

   ```
   2021-11-15T18:45:56.708Z [INFO]  {Main.cpp}: Jobs is enabled
                         .
                         .
                         .
   2021-11-15T18:45:56.708Z [INFO]  {Main.cpp}: Client base has been notified that Jobs has started
   2021-11-15T18:45:56.708Z [INFO]  {JobsFeature.cpp}: Running Jobs!
   2021-11-15T18:45:56.708Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to startNextPendingJobExecution accepted and rejected
   2021-11-15T18:45:56.708Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to nextJobChanged events
   2021-11-15T18:45:56.708Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to updateJobExecutionStatusAccepted for jobId +
   2021-11-15T18:45:56.738Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToUpdateJobExecutionAccepted with code {0}
   2021-11-15T18:45:56.739Z [DEBUG] {JobsFeature.cpp}: Attempting to subscribe to updateJobExecutionStatusRejected for jobId +
   2021-11-15T18:45:56.753Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToNextJobChanged with code {0}
   2021-11-15T18:45:56.760Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToStartNextJobRejected with code {0}
   2021-11-15T18:45:56.776Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToStartNextJobAccepted with code {0}
   2021-11-15T18:45:56.776Z [DEBUG] {JobsFeature.cpp}: Ack received for SubscribeToUpdateJobExecutionRejected with code {0}
   2021-11-15T18:45:56.777Z [DEBUG] {JobsFeature.cpp}: Publishing startNextPendingJobExecutionRequest
   2021-11-15T18:45:56.785Z [DEBUG] {JobsFeature.cpp}: Ack received for StartNextPendingJobPub with code {0}
   2021-11-15T18:45:56.785Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   ```

1. 在終端機視窗中看到此訊息之後，請繼續執行下一個程序並建立任務資源。請注意，它可能不是清單中的最後一個項目。

   ```
   2021-11-15T18:45:56.785Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   ```

**建立 AWS IoT 任務資源**

1. 在本機主機電腦上：

   1. 使用來自 [建立和存放 IoT 任務的任務文件](#iot-dc-runjobs-prepare-define-jobdoc) 的任務文件 URL 來取代 *job\$1document\$1url*。

   1. 使用為裝置建立的物件資源 ARN 來取代 *thing\$1arn*，然後執行此命令。

      ```
      aws iot create-job \
      --job-id hello-world-job-1 \
      --document-source "job_document_url" \
      --targets "thing_arn" \
      --target-selection SNAPSHOT
      ```

      如果成功，命令會傳回類似以下的結果。

      ```
      {
        "jobArn": "arn:aws:iot:us-west-2:57EXAMPLE833:job/hello-world-job-1",
        "jobId": "hello-world-job-1"
      }
      ```

1. 在終端機視窗中，您應該會看到來自 AWS IoT Device Client 的輸出，如下所示。

   ```
   2021-11-15T18:02:26.688Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Job ids differ
   2021-11-15T18:10:24.890Z [INFO]  {JobsFeature.cpp}: Executing job: hello-world-job-1
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Attempting to update job execution status!
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Not including stdout with the status details
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Not including stderr with the status details
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Assuming executable is in PATH
   2021-11-15T18:10:24.890Z [INFO]  {JobsFeature.cpp}: About to execute: echo Hello world!
   2021-11-15T18:10:24.890Z [DEBUG] {Retry.cpp}: Retryable function starting, it will retry until success
   2021-11-15T18:10:24.890Z [DEBUG] {JobsFeature.cpp}: Created EphermalPromise for ClientToken 3TEWba9Xj6 in the updateJobExecution promises map
   2021-11-15T18:10:24.890Z [DEBUG] {JobEngine.cpp}: Child process now running
   2021-11-15T18:10:24.890Z [DEBUG] {JobEngine.cpp}: Child process about to call execvp
   2021-11-15T18:10:24.890Z [DEBUG] {JobEngine.cpp}: Parent process now running, child PID is 16737
   2021-11-15T18:10:24.891Z [DEBUG] {16737}: Hello world!
   2021-11-15T18:10:24.891Z [DEBUG] {JobEngine.cpp}: JobEngine finished waiting for child process, returning 0
   2021-11-15T18:10:24.891Z [INFO]  {JobsFeature.cpp}: Job exited with status: 0
   2021-11-15T18:10:24.891Z [INFO]  {JobsFeature.cpp}: Job executed successfully!
   2021-11-15T18:10:24.891Z [DEBUG] {JobsFeature.cpp}: Attempting to update job execution status!
   2021-11-15T18:10:24.891Z [DEBUG] {JobsFeature.cpp}: Not including stdout with the status details
   2021-11-15T18:10:24.891Z [DEBUG] {JobsFeature.cpp}: Not including stderr with the status details
   2021-11-15T18:10:24.892Z [DEBUG] {Retry.cpp}: Retryable function starting, it will retry until success
   2021-11-15T18:10:24.892Z [DEBUG] {JobsFeature.cpp}: Created EphermalPromise for ClientToken GmQ0HTzWGg in the updateJobExecution promises map
   2021-11-15T18:10:24.905Z [DEBUG] {JobsFeature.cpp}: Ack received for PublishUpdateJobExecutionStatus with code {0}
   2021-11-15T18:10:24.905Z [DEBUG] {JobsFeature.cpp}: Removing ClientToken 3TEWba9Xj6 from the updateJobExecution promises map
   2021-11-15T18:10:24.905Z [DEBUG] {JobsFeature.cpp}: Success response after UpdateJobExecution for job hello-world-job-1
   2021-11-15T18:10:24.917Z [DEBUG] {JobsFeature.cpp}: Ack received for PublishUpdateJobExecutionStatus with code {0}
   2021-11-15T18:10:24.918Z [DEBUG] {JobsFeature.cpp}: Removing ClientToken GmQ0HTzWGg from the updateJobExecution promises map
   2021-11-15T18:10:24.918Z [DEBUG] {JobsFeature.cpp}: Success response after UpdateJobExecution for job hello-world-job-1
   2021-11-15T18:10:25.861Z [INFO]  {JobsFeature.cpp}: No pending jobs are scheduled, waiting for the next incoming job
   ```

1. 當 AWS IoT 裝置用戶端正在執行並等待任務時，您可以透過變更 `job-id`值，並從**create-job**步驟 1 重新執行 來提交另一個任務。

當您完成執行任務時，請在終端機視窗中輸入 ^C(control-C) 以停止 AWS IoT 裝置用戶端。

# 教學課程：執行 AWS IoT Device Client 教學課程後清除
<a name="iot-dc-cleanup"></a>

本教學課程中的程序會在完成此學習路徑中的教學課程時，逐步引導您移除所建立的檔案和資源。

**Topics**
+ [步驟 1：使用 裝置用戶端建置示範後清除 AWS IoT 裝置](#iot-dc-cleanup-devices)
+ [步驟 2：使用 AWS IoT 裝置用戶端建置示範 AWS 帳戶 後清除您的](#iot-dc-cleanup-cloud)

## 步驟 1：使用 裝置用戶端建置示範後清除 AWS IoT 裝置
<a name="iot-dc-cleanup-devices"></a>

本教學課程說明在此學習路徑中建置示範後，如何清除 microSD 卡的兩個選項。選擇提供所需安全等級的選項。

請注意，清除裝置的 microSD 卡不會移除您建立的任何 AWS IoT 資源。若要在清理裝置的 microSD 卡之後清除 AWS IoT 資源，您應該檢閱 上的教學課程[步驟 2：使用 AWS IoT 裝置用戶端建置示範 AWS 帳戶 後清除您的](#iot-dc-cleanup-cloud)。

### 選項 1：透過重新寫入 microSD 記憶卡進行清除
<a name="iot-dc-cleanup-devices-flash"></a>

在完成此學習路徑中的教學課程後，清除 microSD 卡最簡單且最徹底的方法是，使用您在第一次準備裝置時所建立的儲存映像檔案覆寫 microSD 卡。

此程序會使用本機主機電腦，將儲存的 microSD 卡映像寫入 microSD 卡。

**注意**  
如果裝置未針對其作業系統使用卸除式儲存媒體，請參閱該裝置的程序。

**若要將新映像寫入 microSD 卡**

1. 在本機主機電腦上，找出要寫入至 microSD 卡的儲存 microSD 卡映像。

1. 請將 microSD 卡插入主機電腦。

1. 使用 SD 卡映像工具，將選取的影像檔案寫入至 microSD 卡。

1. 寫入 Raspberry Pi 作業系統映像至 microSD 卡後，請退出 microSD 卡並安全地將其從本機主機電腦中移除。

您的 microSD 卡已可供使用。

### 選項 2：透過刪除使用者目錄進行清除
<a name="iot-dc-cleanup-devices-dirs"></a>

若要在完成教學課程後清理 microSD 卡而不重寫 microSD 卡映像，您可以個別刪除使用者目錄。這並不像從儲存映像重寫 microSD 卡那麼徹底，因為此操作不會移除任何可能已安裝的系統檔案。

如果移除使用者目錄足以滿足需求，您可以遵循此程序。

**從裝置刪除此學習路徑的使用者目錄**

1. 在連接至裝置的終端機視窗中，執行這些命令來刪除在此學習路徑中建立的使用者目錄、子目錄及其所有檔案。
**注意**  
在刪除這些目錄和檔案之後，您必須再次完成教學課程，才能執行示範。

   ```
   rm -Rf ~/dc-configs
   rm -Rf ~/policies
   rm -Rf ~/messages
   rm -Rf ~/certs
   rm -Rf ~/.aws-iot-device-client
   ```

1. 在連接至裝置的終端機視窗中，執行這些命令來刪除應用程式來源目錄和檔案。
**注意**  
這些命令不會解除安裝任何程式。它們只會刪除用於建置和安裝它們的來源檔案。刪除這些檔案後， AWS CLI 和 AWS IoT 裝置用戶端可能無法運作。

   ```
   rm -Rf ~/aws-cli
   rm -Rf ~/aws
   rm -Rf ~/aws-iot-device-client
   ```

## 步驟 2：使用 AWS IoT 裝置用戶端建置示範 AWS 帳戶 後清除您的
<a name="iot-dc-cleanup-cloud"></a>

這些程序可協助您識別和移除您在完成此學習路徑中的教學課程時建立 AWS 的資源。

### 清除 AWS IoT 資源
<a name="iot-dc-cleanup-cloud-iot"></a>

此程序可協助您識別和移除您在完成此學習路徑中的教學課程時建立 AWS IoT 的資源。


**AWS IoT 在此學習路徑中建立的資源**  

| 教學課程 | 物件資源 | 政策資源 | 
| --- | --- | --- | 
|  [教學課程：安裝和設定 AWS IoT 裝置用戶端](iot-dc-install-dc.md)  |  **DevCliTestThing**  | DevCliTestThingPolicy | 
|  [教學課程：示範與 AWS IoT 裝置用戶端的 MQTT 訊息通訊](iot-dc-testconn.md)  |  **PubSubTestThing**  | PubSubTestThingPolicy | 
|  [教學課程：使用 AWS IoT 裝置用戶端示範遠端動作 （任務）](iot-dc-runjobs.md)  | 使用者定義 (可能不止一個) |  *使用者定義* (可能不止一個)  | 

**若要刪除 AWS IoT 資源，請遵循您建立的每個物件資源的此程序**

1. 使用要刪除的物件資源名稱來取代 `thing_name`，然後執行此命令從本機主機電腦列出連接至物件資源的憑證。

   ```
   aws iot list-thing-principals --thing-name thing_name
   ```

   此命令會傳回像這樣的回應，其中會列出連接至 `thing_name` 的憑證。在大多數情況下，清單中只會有一個憑證。

   ```
   {
       "principals": [
           "arn:aws:iot:us-west-2:57EXAMPLE833:cert/23853eea3cf0edc7f8a69c74abeafa27b2b52823cab5b3e156295e94b26ae8ac"
       ]
   }
   ```

1. 針對上一個命令列出的每個憑證：

   1. 使用上一個命令的憑證 ID 來取代 `certificate_ID`。憑證 ID 是上一個命令傳回的 ARN 中 `cert/` 後面的英數字元。然後執行此命令來停用憑證。

      ```
      aws iot update-certificate --new-status INACTIVE --certificate-id certificate_ID
      ```

      如果成功，此命令不會傳回任何內容。

   1. 使用之前傳回的憑證清單中的憑證 ARN 來取代 `certificate_ARN`，然後執行此命令來列出連接至此憑證的政策。

      ```
      aws iot list-attached-policies --target certificate_ARN
      ```

      此命令會傳回像這樣的回應，其中會列出連接至憑證的政策。在大多數情況下，清單中只會有一個政策。

      ```
      {
          "policies": [
              {
                  "policyName": "DevCliTestThingPolicy",
                  "policyArn": "arn:aws:iot:us-west-2:57EXAMPLE833:policy/DevCliTestThingPolicy"
              }
          ]
      }
      ```

   1. 每個連接至憑證的政策：

      1. 使用上一個命令的 `policyName` 值來取代 `policy_name`，使用憑證的 ARN 來取代 `certificate_ARN`，然後執行此命令從憑證分離政策。

         ```
         aws iot detach-policy --policy-name policy_name --target certificate_ARN
         ```

         如果成功，此命令不會傳回任何內容。

      1. 使用 `policyName` 值來取代 `policy_name`，然後執行此命令，查看政策是否已連接至任何憑證。

         ```
         aws iot list-targets-for-policy --policy-name policy_name
         ```

         如果命令傳回類似這樣的空白清單，代表政策未連接至任何憑證，您可以繼續列出政策版本。如果仍有連接至政策的憑證，請繼續進行 **detach-thing-principal** 步驟。

         ```
         {
             "targets": []
         }
         ```

      1. 使用 `policyName` 值來取代 `policy_name`，然後執行此命令來檢查政策版本。若要刪除政策，該政策必須只有一個版本。

         ```
         aws iot list-policy-versions --policy-name policy_name
         ```

         如果政策只有一個版本 (例如此範例)，您可以跳至 **delete-policy** 步驟，然後立即刪除政策。

         ```
         {
             "policyVersions": [
                 {
                     "versionId": "1",
                     "isDefaultVersion": true,
                     "createDate": "2021-11-18T01:02:46.778000+00:00"
                 }
             ]
         }
         ```

         如果政策具有多個版本 (例如此範例)，就必須先刪除具有 `isDefaultVersion` 值的 `false`，才能刪除政策。

         ```
         {
             "policyVersions": [
                 {
                     "versionId": "2",
                     "isDefaultVersion": true,
                     "createDate": "2021-11-18T01:52:04.423000+00:00"
                 },
                 {
                     "versionId": "1",
                     "isDefaultVersion": false,
                     "createDate": "2021-11-18T01:30:18.083000+00:00"
                 }
             ]
         }
         ```

         如果需要刪除政策版本，請使用 `policyName` 值來取代 `policy_name`，使用上一個命令的 `versionId` 值取代 `version_ID`，然後執行此命令來刪除政策版本。

         ```
         aws iot delete-policy-version --policy-name policy_name --policy-version-id version_ID
         ```

         如果成功，此命令不會傳回任何內容。

         刪除政策版本後，請重複此步驟，直到政策只有一個政策版本為止。

      1. 使用 `policyName` 值來取代 `policy_name`，然後執行此命令來刪除政策。

         ```
         aws iot delete-policy --policy-name policy_name
         ```

   1. 使用物件的名稱來取代 `thing_name`，再使用憑證的 ARN 來取代 `certificate_ARN`，然後執行此命令來從物件資源分離憑證。

      ```
      aws iot detach-thing-principal --thing-name thing_name --principal certificate_ARN
      ```

      如果成功，此命令不會傳回任何內容。

   1. 使用上一個命令的憑證 ID 來取代 `certificate_ID`。憑證 ID 是上一個命令傳回的 ARN 中 `cert/` 後面的英數字元。然後執行此命令來刪除憑證資源。

      ```
      aws iot delete-certificate --certificate-id certificate_ID
      ```

      如果成功，此命令不會傳回任何內容。

1. 使用物件的名稱來取代 `thing_name`，然後執行此命令來刪除該物件。

   ```
   aws iot delete-thing --thing-name thing_name
   ```

   如果成功，此命令不會傳回任何內容。

### 清除 AWS 資源
<a name="iot-dc-cleanup-cloud-aws"></a>

此程序可協助您識別和移除您在完成此學習路徑中的教學課程時建立的其他 AWS 資源。


**在此學習路徑中建立的其他 AWS 資源**  

| 教學課程 | Resource Type (資源類型) | 資源名稱或 ID | 
| --- | --- | --- | 
|  [教學課程：使用 AWS IoT 裝置用戶端示範遠端動作 （任務）](iot-dc-runjobs.md)  | Amazon S3 物件 | hello-world-job.json | 
|  [教學課程：使用 AWS IoT 裝置用戶端示範遠端動作 （任務）](iot-dc-runjobs.md)  |  AWS IoT 任務資源  | 使用者定義 | 

**刪除在此學習路徑中建立 AWS 的資源**

1. 刪除在此學習路徑中建立的任務

   1. 執行此命令以列出 中的任務 AWS 帳戶。

      ```
      aws iot list-jobs
      ```

      命令會傳回您 AWS 帳戶 和 AWS 區域 中看起來像這樣的 AWS IoT 任務清單。

      ```
      {
          "jobs": [
              {
                  "jobArn": "arn:aws:iot:us-west-2:57EXAMPLE833:job/hello-world-job-2",
                  "jobId": "hello-world-job-2",
                  "targetSelection": "SNAPSHOT",
                  "status": "COMPLETED",
                  "createdAt": "2021-11-16T23:40:36.825000+00:00",
                  "lastUpdatedAt": "2021-11-16T23:40:41.375000+00:00",
                  "completedAt": "2021-11-16T23:40:41.375000+00:00"
              },
              {
                  "jobArn": "arn:aws:iot:us-west-2:57EXAMPLE833:job/hello-world-job-1",
                  "jobId": "hello-world-job-1",
                  "targetSelection": "SNAPSHOT",
                  "status": "COMPLETED",
                  "createdAt": "2021-11-16T23:35:26.381000+00:00",
                  "lastUpdatedAt": "2021-11-16T23:35:29.239000+00:00",
                  "completedAt": "2021-11-16T23:35:29.239000+00:00"
              }
          ]
      }
      ```

   1. 對於您從清單中辨識為在此學習路徑中建立任務的每個任務，請將 `jobId`取代為要刪除的任務`jobId`值，然後執行此命令來刪除 AWS IoT 任務。

      ```
      aws iot delete-job --job-id jobId
      ```

      如果成功，此命令不會傳回任何內容。

1. 刪除儲存在此學習路徑 Amazon S3 儲存貯體中的任務文件

   1. 使用您採用的儲存貯體名稱來取代 `bucket`，然後執行此命令來列出您使用的 Amazon S3 儲存貯體中的物件。

      ```
      aws s3api list-objects --bucket bucket
      ```

      此命令會傳會儲存貯體中的 Amazon S3 物件清單，如下所示。

      ```
      {
          "Contents": [
              {
                  "Key": "hello-world-job.json",
                  "LastModified": "2021-11-18T03:02:12+00:00",
                  "ETag": "\"868c8bc3f56b5787964764d4b18ed5ef\"",
                  "Size": 54,
                  "StorageClass": "STANDARD",
                  "Owner": {
                      "DisplayName": "EXAMPLE",
                      "ID": "e9e3d6ec1EXAMPLEf5bfb5e6bd0a2b6ed03884d1ed392a82ad011c144736a4ee"
                  }
              },
              {
                  "Key": "iot_job_firmware_update.json",
                  "LastModified": "2021-04-13T21:57:07+00:00",
                  "ETag": "\"7c68c591949391791ecf625253658c61\"",
                  "Size": 66,
                  "StorageClass": "STANDARD",
                  "Owner": {
                      "DisplayName": "EXAMPLE",
                      "ID": "e9e3d6ec1EXAMPLEf5bfb5e6bd0a2b6ed03884d1ed392a82ad011c144736a4ee"
                  }
              },
              {
                  "Key": "order66.json",
                  "LastModified": "2021-04-13T21:57:07+00:00",
                  "ETag": "\"bca60d5380b88e1a70cc27d321caba72\"",
                  "Size": 29,
                  "StorageClass": "STANDARD",
                  "Owner": {
                      "DisplayName": "EXAMPLE",
                      "ID": "e9e3d6ec1EXAMPLEf5bfb5e6bd0a2b6ed03884d1ed392a82ad011c144736a4ee"
                  }
              }
          ]
      }
      ```

   1. 對於您從清單中辨識為在此學習路徑中建立的物件的每個物件，請使用儲存貯體名稱來取代 `bucket`，使用要刪除物件的鍵值來取代 `key`，然後執行此命令來刪除 Amazon S3 物件。

      ```
       aws s3api delete-object --bucket bucket --key key
      ```

      如果成功，此命令不會傳回任何內容。

刪除完成此學習路徑時建立的所有 AWS 資源和物件後，您可以重新開始並重複教學課程。

# 使用 AWS IoT 裝置SDKs建置解決方案
<a name="iot-tutorials-sdk-intro"></a>

本節中的教學課程將逐步引導您開發可使用 部署到生產環境的 IoT 解決方案 AWS IoT。

這些教學課程可能需要比 章節中更多的時間來完成，[使用 AWS IoT 裝置用戶端建置示範](iot-tutorials-dc-intro.md)因為它們使用 AWS IoT 裝置SDKs並更詳細地解釋正在套用的概念，以協助您建立安全可靠的解決方案。

## 使用 AWS IoT 裝置SDKs開始建置解決方案
<a name="iot-sdk-tutorial-overview"></a>

這些教學課程會逐步解說不同的 AWS IoT 案例。在適當的情況下，教學課程會使用 AWS IoT 裝置 SDKs。

**Topics**
+ [使用 AWS IoT 裝置SDKs開始建置解決方案](#iot-sdk-tutorial-overview)
+ [教學課程： AWS IoT Core 使用 裝置 SDK 將 AWS IoT 裝置連線至](sdk-tutorials.md)
+ [建立 AWS IoT 規則將裝置資料路由到其他 服務](iot-rules-tutorial.md)
+ [在裝置離線時保留裝置狀態](iot-shadows-tutorial.md)
+ [教學課程：為 建立自訂授權方 AWS IoT Core](custom-auth-tutorial.md)
+ [教學課程：使用 AWS IoT 和 Raspberry Pi 監控土壤濕度](iot-moisture-tutorial.md)

# 教學課程： AWS IoT Core 使用 裝置 SDK 將 AWS IoT 裝置連線至
<a name="sdk-tutorials"></a>

本教學課程示範如何將裝置連線至 ， AWS IoT Core 以便傳送和接收進出的資料 AWS IoT。完成本教學課程後，您的裝置將設定為連線至 ， AWS IoT Core 而且您將了解裝置與 的通訊方式 AWS IoT。

**Topics**
+ [先決條件](#sdk-tutorials-prereq)
+ [為 準備您的裝置 AWS IoT](#sdk-tutorials-prepare)
+ [檢閱 MQTT 通訊協定](#sdk-tutorials-mqtt-review)
+ [檢閱 pubsub.py 裝置 SDK 範例應用程式](#sdk-tutorials-explore-sample)
+ [連接您的裝置並與 通訊 AWS IoT Core](#sdk-tutorials-experiment)
+ [檢視結果](#sdk-tutorials-conclusion)
+ [教學課程：使用 適用於 Embedded C 的 AWS IoT Device SDK](iot-embedded-c-sdk.md)

## 先決條件
<a name="sdk-tutorials-prereq"></a>

開始本教學課程之前，請確定您有：
+ 

**已完成 [AWS IoT Core 教學課程入門](iot-gs.md)**  
在該教學課程中您必須進行 [設定您的裝置](configure-device.md) 的部分中，請為您的裝置選取 [連接 Raspberry Pi 或其他裝置](connecting-to-existing-device.md) 選項，並使用 Python 語言選項來配置您的裝置。
**注意**  
讓該教學課程中的終端機視窗處於開啟狀態，因為您還會在本教學課程中用到它。
+ 

**可執行適用於 Python 的 AWS IoT Device SDK v2 的裝置。**  
本教學課程說明如何使用 Python AWS IoT Core 程式碼範例將裝置連接至 ，這需要相對強大的裝置。若您使用是資源受限的裝置，這些程式碼範例可能無法在這些裝置上運作。在這種情況下，您可能會在[教學課程：使用 適用於 Embedded C 的 AWS IoT Device SDK](iot-embedded-c-sdk.md)教學課程中獲得更多成功。
+ 

**取得連線至裝置所需的資訊**  
若要將裝置連線至 AWS IoT，您必須擁有物件名稱、主機名稱和連接埠號碼的相關資訊。
**注意**  
您也可以使用自訂身分驗證來連接裝置 AWS IoT Core。您傳遞給授權方 Lambda 函數的連線資料取決於您使用的通訊協定。
  + **物件名稱**：您要連線的 AWS IoT 物件名稱。您必須已將 註冊為裝置做為 AWS IoT 物件。如需詳細資訊，請參閱[使用 管理裝置 AWS IoT](iot-thing-management.md)。
  + **主機名稱**：帳戶特定 IoT 端點的主機名稱。
  + **連接埠號碼**：要連線的連接埠號碼。

  您可以使用 AWS IoT Python SDK 中的 `configureEndpoint`方法來設定主機名稱和連接埠號碼。

  ```
  myAWSIoTMQTTClient.configureEndpoint("random.iot.region.amazonaws.com", 8883)
  ```

## 為 準備您的裝置 AWS IoT
<a name="sdk-tutorials-prepare"></a>

在 [AWS IoT Core 教學課程入門](iot-gs.md) 中，您準備好裝置和 AWS 帳戶，使其可進行通訊。本節會檢閱適用於任何裝置連線之準備工作的各個層面 AWS IoT Core。

若為要連線至 AWS IoT Core的裝置：

1. 您必須具有 **AWS 帳戶**。

    AWS 帳戶 如果您還沒有 ， 中的程序會[設定 AWS 帳戶](setting-up.md)說明如何建立 。

1. 在該帳戶中，您必須為 AWS 帳戶 和 區域中的裝置定義下列**AWS IoT 資源**。

   程序[建立 AWS IoT 資源](create-iot-resources.md) 中的程序說明如何為您在 AWS 帳戶 和區域中的裝置建立這些資源。
   + 以 AWS IoT 註冊並啟用以驗證裝置的**裝置憑證**。

     憑證通常是使用 **AWS IoT 物件**建立並加以連接。雖然裝置不需要物件才能連線 AWS IoT，但它可讓裝置使用其他 AWS IoT 功能。
   + 連接到裝置憑證**的政策**，授權它連接到 AWS IoT Core 並執行您想要它的所有動作。

1. 可存取您 AWS 帳戶之裝置端點的**網際網路連線**。

   裝置端點會在 中說明[AWS IoT 裝置資料和服務端點](iot-connect-devices.md#iot-connect-device-endpoints)，並可在 [AWS IoT 主控台的設定頁面](https://console.aws.amazon.com/iot/home#/settings)中查看。

1. **通訊軟體**，例如 AWS IoT 裝置 SDK 提供。本教學課程使用[適用於 Python 的AWS IoT 裝置 SDK v2](https://github.com/aws/aws-iot-device-sdk-python-v2#aws-iot-device-sdk-v2-for-python)。

## 檢閱 MQTT 通訊協定
<a name="sdk-tutorials-mqtt-review"></a>

在我們談論範例應用程式之前，其有助於了解 MQTT 通訊協定。MQTT 通訊協定提供了一些優於其他網路通訊協定 (如 HTTP) 的優勢，這使其成為 IoT 裝置的熱門選擇。本節將會檢視 MQTT 適用於本教學課程的主要層面。如需 MQTT 與 HTTP 比較的資訊，請參閱 [選擇裝置通訊的應用程式通訊協定](protocols.md#protocol-selection)。

**MQTT 使用一個發佈/訂閱通訊模型。**  
MQTT 通訊協定會與其主機一起使用發佈/訂閱通訊模型。此模型與 HTTP 使用的請求/回應模型不同。使用 MQTT，裝置會與由唯一用戶端 ID 識別的主機建立工作階段。如要傳送資料，裝置會將主題識別的訊息發佈至主機中的訊息代理程式。為了收到訊息代理程式的訊息，裝置會在訂閱請求中傳送主題篩選條件給訊息代理程式，以訂閱其會收到的主題。

**MQTT 支援持久性工作階段**  
訊息代理程式會收到來自裝置的訊息，並將訊息發佈至已加以訂閱的裝置。利用[持久性工作階段](mqtt.md#mqtt-persistent-sessions) (即使啟動裝置以中斷連線，工作階段仍保持活動狀態)，裝置可擷取中斷連線時所發佈的訊息。在裝置端，MQTT 支援服務品質層級 ([QoS](mqtt.md#mqtt-qos))，以確保主機接收裝置所傳送的訊息。

## 檢閱 pubsub.py 裝置 SDK 範例應用程式
<a name="sdk-tutorials-explore-sample"></a>

本節會從用於本教學課程中之**適用於 Python 的AWS IoT 裝置 SDK v2** 檢閱 `pubsub.py` 範例應用程式。在這裡，我們將檢閱其如何連線至 AWS IoT Core 以發佈和訂閱 MQTT 訊息。下一節提供一些練習，協助您探索裝置連線和通訊的方式 AWS IoT Core。

**`pubsub.py` 範例應用程式示範 MQTT 連線的這些層面 AWS IoT Core：**
+ [通訊協定](#sdk-tutorials-explore-protocols)
+ [持久性工作階段](#sdk-tutorials-explore-persistent)
+ [服務品質](#sdk-tutorials-explore-qos)
+ [訊息發佈](#sdk-tutorials-explore-publish)
+ [訊息訂閱](#sdk-tutorials-explore-subscribe)
+ [裝置中斷連線及重新連線](#sdk-tutorials-explore-connect)

### 通訊協定
<a name="sdk-tutorials-explore-protocols"></a>

`pubsub.py` 範例會示範使用 MQTT 和透過 WSS 的 MQTT 通訊協定的 MQTT 連線。[AWS 通用執行時間 (AWS CRT)](https://github.com/awslabs/aws-crt-python#aws-crt-python) 程式庫提供低階通訊協定支援，並包含在適用於 Python 的 AWS IoT Device SDK v2 中。

#### MQTT
<a name="sdk-tutorials-explore-mqtt"></a>

中使用 AWS IoT Core MQTT 通訊協定[https://github.com/awslabs/aws-crt-python/blob/89207bcf1387177034e02fe29e8e469ca45e39b7/awscrt/awsiot_mqtt_connection_builder.py](https://github.com/awslabs/aws-crt-python/blob/89207bcf1387177034e02fe29e8e469ca45e39b7/awscrt/awsiot_mqtt_connection_builder.py)與 建立連線`pubsub.py`的範例呼叫 `mtls_from_path`（如下所示）。 `mtls_from_path`使用 X.509 憑證和 TLS v1.2 來驗證裝置。 AWS CRT 程式庫會處理該連線的較低層級詳細資訊。

```
mqtt_connection = mqtt_connection_builder.mtls_from_path(
    endpoint=args.endpoint,
    cert_filepath=args.cert,
    pri_key_filepath=args.key,
    ca_filepath=args.ca_file,
    client_bootstrap=client_bootstrap,
    on_connection_interrupted=on_connection_interrupted,
    on_connection_resumed=on_connection_resumed,
    client_id=args.client_id,
    clean_session=False,
    keep_alive_secs=6
)
```

`endpoint`  
 AWS 帳戶您的 IoT 裝置端點  
於範例應用程式中，此值會從命令列傳入。

`cert_filepath`  
裝置憑證檔案的路徑。  
於範例應用程式中，此值會從命令列傳入。

`pri_key_filepath`  
使用其憑證檔案建立的裝置私密金鑰檔案路徑  
於範例應用程式中，此值會從命令列傳入。

`ca_filepath`  
根 CA 檔案的路徑。僅當 MQTT 伺服器使用不在您信任庫中的憑證時才需要。  
於範例應用程式中，此值會從命令列傳入。

`client_bootstrap`  
處理通訊端通訊活動的通用執行時間物件  
在範例應用程式中，此物件就在呼叫 `mqtt_connection_builder.mtls_from_path` 之前進行實例化。

`on_connection_interrupted``on_connection_resumed`  
裝置連線遭到中斷並回復時呼叫的回呼函數。

`client_id`  
唯一在 AWS 區域中識別此裝置的 ID。  
於範例應用程式中，此值會從命令列傳入。

`clean_session`  
是否啟動新的持續性工作階段，或者，若存在，則重新連接到現有的工作階段

`keep_alive_secs`  
在 `CONNECT` 請求中傳送的保持活動值 (以秒為單位)。Ping 會在此時間間隔自動傳送。若在此值的 1.5 倍之後未收到 ping，則伺服器會假設連線中斷。

#### 透過 WSS 的 MQTT
<a name="sdk-tutorials-explore-mqtt-wss"></a>

`pubsub.py` 範例呼叫 [https://github.com/awslabs/aws-crt-python/blob/89207bcf1387177034e02fe29e8e469ca45e39b7/awscrt/awsiot_mqtt_connection_builder.py](https://github.com/awslabs/aws-crt-python/blob/89207bcf1387177034e02fe29e8e469ca45e39b7/awscrt/awsiot_mqtt_connection_builder.py) 中的 `websockets_with_default_aws_signing` (如圖所示)，使用透過 WSS 的 MQTT 通訊協定來建立與 AWS IoT Core 的連線。`websockets_with_default_aws_signing` 會使用 [Signature 第 4 版](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)透過 WSS 建立 MQTT 連線，來驗證裝置。

```
mqtt_connection = mqtt_connection_builder.websockets_with_default_aws_signing(
    endpoint=args.endpoint,
    client_bootstrap=client_bootstrap,
    region=args.signing_region,
    credentials_provider=credentials_provider,
    websocket_proxy_options=proxy_options,
    ca_filepath=args.ca_file,
    on_connection_interrupted=on_connection_interrupted,
    on_connection_resumed=on_connection_resumed,
    client_id=args.client_id,
    clean_session=False,
    keep_alive_secs=6
)
```

`endpoint`  
 AWS 帳戶您的 IoT 裝置端點  
於範例應用程式中，此值會從命令列傳入。

`client_bootstrap`  
處理通訊端通訊活動的通用執行時間物件  
在範例應用程式中，此物件就在呼叫 `mqtt_connection_builder.websockets_with_default_aws_signing` 之前進行實例化。

`region`  
Signature V4 身分驗證所使用的 AWS 簽署區域。於 `pubsub.py` 中，其會傳遞在命令列中輸入的參數。  
於範例應用程式中，此值會從命令列傳入。

`credentials_provider`  
提供用於身分驗證的 AWS 登入資料  
在範例應用程式中，此物件就在呼叫 `mqtt_connection_builder.websockets_with_default_aws_signing` 之前進行實例化。

`websocket_proxy_options`  
HTTP 代理選項 (若使用代理主機)  
在範例應用程式中，此值就在呼叫 `mqtt_connection_builder.websockets_with_default_aws_signing` 之前進行初始化。

`ca_filepath`  
根 CA 檔案的路徑。僅當 MQTT 伺服器使用不在您信任庫中的憑證時才需要。  
於範例應用程式中，此值會從命令列傳入。

`on_connection_interrupted``on_connection_resumed`  
裝置連線遭到中斷並回復時呼叫的回呼函數。

`client_id`  
在 AWS 區域中唯一識別此裝置的 ID。  
於範例應用程式中，此值會從命令列傳入。

`clean_session`  
是否啟動新的持續性工作階段，或者，若存在，則重新連接到現有的工作階段

`keep_alive_secs`  
在 `CONNECT` 請求中傳送的保持活動值 (以秒為單位)。Ping 會在此時間間隔自動傳送。若在此值的 1.5 倍之後未收到 ping，則伺服器會假設連線中斷。

#### HTTPS
<a name="sdk-tutorials-explore-https"></a>

HTTPS 如何？ AWS IoT Core 支援發佈 HTTPS 請求的裝置。從程式設計的角度來看，裝置會將 HTTPS 請求傳送至 AWS IoT Core ，就像任何其他應用程式一樣。有關從裝置傳送 HTTP 訊息的 Python 程式範例，請參閱使用 Python `requests` 程式庫的 [HTTPS 程式碼範例](http.md#codeexample)。此範例 AWS IoT Core 使用 HTTPS 傳送訊息至 ， AWS IoT Core 讓 將其解譯為 MQTT 訊息。

雖然 AWS IoT Core 支援來自裝置的 HTTPS 請求，但請務必檢閱 的相關資訊，[選擇裝置通訊的應用程式通訊協定](protocols.md#protocol-selection)以便您可以針對裝置通訊所使用的通訊協定做出明智的決策。

### 持久性工作階段
<a name="sdk-tutorials-explore-persistent"></a>

於範例應用程式中，將 `clean_session` 參數設定為 `False` 表示連線應該是持續的。於實踐中，這意味著透過此呼叫開啟的連線重新連接至現有的持久性工作階段 (如若存在)。否則，其會建立並連線至新的持續工作階段。

使用持續性工作階段，在裝置未連線時，訊息代理程式會儲存傳送至裝置的訊息。當裝置重新連線至持續性工作階段時，訊息代理程式會將所有已訂閱的儲存訊息傳送至裝置。

若無持續性工作階段，裝置將不會收到裝置未連線時傳送的訊息。要使用哪個選項取決於您的應用程式，及是否必須對裝置未連接時產生訊息進行通訊。如需詳細資訊，請參閱[MQTT 持久性工作階段](mqtt.md#mqtt-persistent-sessions)。

### 服務品質
<a name="sdk-tutorials-explore-qos"></a>

當裝置發佈和訂閱訊息時，可以設定偏好的服務品質 (QoS)。 AWS IoT 支援 QoS 層級 0 和 1 以進行發佈和訂閱操作。如需 中 QoS 層級的詳細資訊 AWS IoT，請參閱 [MQTT 服務品質 (QoS) 選項](mqtt.md#mqtt-qos)。

Python 的 AWS CRT 執行期會為其支援的 QoS 層級定義這些常數：


**Python 服務品質層級**  

| MQTT QoS 層級 | SDK 所使用的 Python 符號值 | Description | 
| --- | --- | --- | 
| QoS 層級 0 | mqtt.QoS.AT\$1MOST\$1ONCE | 無論是否收到訊息，都只會嘗試傳送一次訊息。該訊息可能根本不會傳送，例如，若裝置未連線或網路發生錯誤。 | 
| QoS 層級 1 | mqtt.QoS.AT\$1LEAST\$1ONCE | 訊息會重複傳送，直到收到 PUBACK 確認為止。 | 

於範例應用程式中，發佈和訂閱請求的 QoS 層級為 1 (`mqtt.QoS.AT_LEAST_ONCE`)。
+ 

**發佈時的 QoS**  
當裝置發佈 QoS 層級 1 的訊息時，其會重複傳送訊息，直到收到來自訊息代理程式的 `PUBACK` 回應為止。若裝置未連線，訊息會在重新連線後佇列等待傳送。
+ 

**訂閱時的 QoS**  
當裝置訂閱 QoS 層級 1 的訊息時，訊息代理程式會儲存裝置訂閱的訊息，直至其可傳送至裝置為止。訊息代理程式會重新傳送訊息，直至收到來自裝置的 `PUBACK` 回應。

### 訊息發佈
<a name="sdk-tutorials-explore-publish"></a>

成功建立與 的連線後 AWS IoT Core，裝置可以發佈訊息。`pubsub.py` 範例經由呼叫 `mqtt_connection` 物件的 `publish` 操作來完成此作業。

```
mqtt_connection.publish(
    topic=args.topic,
    payload=message,
    qos=mqtt.QoS.AT_LEAST_ONCE
)
```

`topic`  
識別訊息的訊息主題名稱  
於範例應用程式中，這會從命令列傳入。

`payload`  
將訊息承載格式化為字串 (例如，JSON 文件)  
於範例應用程式中，這會從命令列傳入。  
JSON 文件是一種常見的承載格式，並且由其他服務辨識 AWS IoT ；不過，訊息承載的資料格式可以是發佈者和訂閱者同意的任何內容。但在某些狀況下，對大多數的作業而言，其他 AWS IoT 服務僅識別 JSON 和 CBOR。

`qos`  
此訊息的 QoS 層級

### 訊息訂閱
<a name="sdk-tutorials-explore-subscribe"></a>

若要接收來自 AWS IoT 和其他 服務和裝置的訊息，裝置會依其主題名稱訂閱這些訊息。裝置可透過指定[主題名稱](topics.md#topicnames)訂閱個別訊息，及透過指定可包含萬用字元字的[主題篩選條件](topics.md#topicfilters)訂閱一組訊息。`pubsub.py` 範例會使用顯示於此處的程式碼來訂閱訊息，並註冊回呼函數，以於收到訊息之後進行處理。

```
subscribe_future, packet_id = mqtt_connection.subscribe(
    topic=args.topic,
    qos=mqtt.QoS.AT_LEAST_ONCE,
    callback=on_message_received
)
subscribe_result = subscribe_future.result()
```

`topic`  
要訂閱的主題。此可為主題名稱或主題篩選條件。  
於範例應用程式中，這會從命令列傳入。

`qos`  
訊息代理程式是否應該在裝置中斷連線斷時儲存這些訊息。  
`mqtt.QoS.AT_LEAST_ONCE` 的值 (QoS 層級 1) 需要在建立連線時指定持久性工作階段 (`clean_session=False`)。

`callback`  
呼叫來處理訂閱訊息的函數。

此 `mqtt_connection.subscribe` 函式會傳回一個未來和一個封包 ID。若訂閱請求已順利啟動，傳回的封包 ID 大於 0。如要確定訊息代理程式收到訂閱並已註冊，您必須等待非同步作業的結果傳回，如程式碼範例中所示。

**回呼函數**  
`pubsub.py` 範例中的回呼會在裝置收到訂閱訊息時進行處理。

```
def on_message_received(topic, payload, **kwargs):
    print("Received message from topic '{}': {}".format(topic, payload))
    global received_count
    received_count += 1
    if received_count == args.count:
        received_all_event.set()
```

`topic`  
訊息的主題  
即使您已訂閱了主題篩選條件，此為所接收訊息的特定主題名稱。

`payload`  
訊息承載  
此格式為應用程式專用。

`kwargs`  
可能的其他引數，如 [https://awslabs.github.io/aws-crt-python/api/mqtt.html#awscrt.mqtt.Connection.subscribe](https://awslabs.github.io/aws-crt-python/api/mqtt.html#awscrt.mqtt.Connection.subscribe) 中所述。

在 `pubsub.py` 範例中，`on_message_received` 只會顯示主題及其承載。其還會計算在達到限制後，所收到結束程式的訊息。

您的應用程式會評估主題和承載，以決定要執行的動作。

### 裝置中斷連線及重新連線
<a name="sdk-tutorials-explore-connect"></a>

`pubsub.py` 範例包含在裝置中斷連線及重新建立連線時呼叫的回呼函數。您的裝置對這些事件採取的動作為應用程式專用。

裝置首次連線時，必須訂閱要接收的主題。若裝置的工作階段在重新連線時存在，則會還原其訂閱，並在重新連線後將來自這些訂閱的任何儲存訊息傳送至裝置。

若裝置的工作階段在重新連線時不復存在，則必須重新訂閱其訂閱。持續性工作階段具有限的存留期，當裝置中斷連線過久時，可能會過期。

## 連接您的裝置並與 通訊 AWS IoT Core
<a name="sdk-tutorials-experiment"></a>

本節提供一些練習，協助您探索將裝置連線至 AWS IoT Core的不同層面。於這些練習中，您將會使用 AWS IoT 主控台中的 [MQTT 測試用戶端](https://console.aws.amazon.com/iot/home#/test)，查看裝置發佈的內容，及將訊息發佈至裝置。這些練習使用來自[適用於 Python 的AWS IoT 裝置 SDK v2](https://github.com/aws/aws-iot-device-sdk-python-v2/tree/master/samples#sample-apps-for-the-aws-iot-device-sdk-v2-for-python) 的 [https://github.com/aws/aws-iot-device-sdk-python-v2/blob/master/samples/pubsub.py](https://github.com/aws/aws-iot-device-sdk-python-v2/blob/master/samples/pubsub.py) 範例，並以您 [AWS IoT Core 教學課程入門](iot-gs.md) 教學課程經驗為基礎。

**Topics**
+ [訂閱萬用字元主題篩選條件](#sdk-tutorials-experiment-wild)
+ [處理主題篩選條件訂閱](#sdk-tutorials-experiment-process)
+ [從您的裝置發佈訊息](#sdk-tutorials-experiment-publish)

對於這些練習，您會從 `pubsub.py` 範例程式開始。

**注意**  
這些練習假設您已完成 [AWS IoT Core 教學課程入門](iot-gs.md) 教學課程，並使用該教學課程中的裝置終端機視窗。

### 訂閱萬用字元主題篩選條件
<a name="sdk-tutorials-experiment-wild"></a>

在本練習中，您會修改用來呼叫 `pubsub.py` 以訂閱萬用字元主題篩選條件並根據訊息主題處理所接收訊息的命令列。

#### 演練程序
<a name="sdk-tutorials-experiment-wild-steps"></a>

在此練習中，想像您的裝置包含溫度控制和光源控制。其會使用這些主題名稱來識別與其相關的訊息。

1. 開始練習之前，請試著從裝置上的 [AWS IoT Core 教學課程入門](iot-gs.md) 教學課程執行此命令，確保所有項目都準備好進行練習。

   ```
   cd ~/aws-iot-device-sdk-python-v2/samples
   python3 pubsub.py --topic topic_1 --ca_file ~/certs/Amazon-root-CA-1.pem --cert ~/certs/device.pem.crt --key ~/certs/private.pem.key --endpoint your-iot-endpoint
   ```

   您應該會看到與在[教學課程入門](connecting-to-existing-device.md#gs-device-node-app-run)中看到的相同輸出。

1. 在此練習中，請變更這些命令列參數。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/sdk-tutorials.html)

   對初始命令列進行這些變更會產生此命令列。在裝置的終端機視窗中輸入此命令。

   ```
   python3 pubsub.py --message "" --count 2 --topic device/+/details --ca_file ~/certs/Amazon-root-CA-1.pem --cert ~/certs/device.pem.crt --key ~/certs/private.pem.key --endpoint your-iot-endpoint
   ```

   程式應該會顯示如下所示的內容：

   ```
   Connecting to a3qexamplesffp-ats.iot.us-west-2.amazonaws.com with client ID 'test-24d7cdcc-cc01-458c-8488-2d05849691e1'...
   Connected!
   Subscribing to topic 'device/+/details'...
   Subscribed with QoS.AT_LEAST_ONCE
   Waiting for all messages to be received...
   ```

   若您在終端機上看到類似的內容，表示您的裝置已準備就緒，且會收聽主題名稱開頭為 `device`，結尾為 `/detail` 的訊息。所以，讓我們來進行測試。

1. 以下為您的裝置可能會收到的幾個訊息。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/sdk-tutorials.html)

1. 在 AWS IoT 主控台中使用 MQTT 測試用戶端，將上一個步驟中所述的訊息傳送到您的裝置。

   1. 在 AWS IoT 主控台中開啟 [MQTT 測試用戶端](https://console.aws.amazon.com/iot/home#/test)。

   1. 於 **Subscribe to a topic** (訂閱主題) 的 **Subscription topic** (訂閱主題) 欄位中，輸入主題篩選條件：**device/\$1/details**，再選擇 **Subscribe to topic** (訂閱主題)。

   1. 在 MQTT 測試用戶端的 **Subscriptions** (訂閱) 欄中，選擇 **device/\$1/details**。

   1. 若為上表中的每個主題，請於 MQTT 測試用戶端中執行下列動作：

      1. 於 **Publish** (發佈) 中，輸入來自表格中 **Topic name** (主題名稱) 欄的值。

      1. 在主題名稱下方的訊息承載欄位中，輸入來自表格中 **Message payload** (訊息承載) 欄的值。

      1. 觀看 `pubsub.py` 正在執行的終端機視窗，並在 MQTT 測試用戶端中，選擇 **Publish to topic** (發佈至主題)。

      您應該看到該訊息是由終端機視窗中的 `pubsub.py` 所收到。

#### 演練結果
<a name="sdk-tutorials-experiment-wild-result"></a>

有了此 `pubsub.py`，使用萬用字元主題篩選條件訂閱訊息，加以訊息，並將其顯示於終端機視窗中。請注意您如何訂閱單一主題篩選條件，並呼叫回呼函數來處理具有兩個不同主題的訊息。

### 處理主題篩選條件訂閱
<a name="sdk-tutorials-experiment-process"></a>

建置於上一個練習上，修改 `pubsub.py` 範例應用程式來評估訊息主題，並根據主題處理訂閱的訊息。

#### 演練程序
<a name="sdk-tutorials-experiment-process-steps"></a>

**如要評估訊息主題**

1. 將 `pubsub.py` 複製至 `pubsub2.py`。

1. 以您最愛的文字編輯器或 IDE 中開啟 `pubsub2.py` 檔案。

1. 在 `pubsub2.py` 中，尋找 `on_message_received` 函數。

1. 在 `on_message_received` 中，請在以 `print("Received message` 開頭的行之後及以 `global received_count` 開頭的行之前插入下列程式碼。

   ```
       topic_parsed = False
       if "/" in topic:
           parsed_topic = topic.split("/")
           if len(parsed_topic) == 3:
               # this topic has the correct format
               if (parsed_topic[0] == 'device') and (parsed_topic[2] == 'details'):
                   # this is a topic we care about, so check the 2nd element
                   if (parsed_topic[1] == 'temp'):
                       print("Received temperature request: {}".format(payload))
                       topic_parsed = True
                   if (parsed_topic[1] == 'light'):
                       print("Received light request: {}".format(payload))
                       topic_parsed = True
       if not topic_parsed:
           print("Unrecognized message topic.")
   ```

1. 儲存您的變更，並使用此命令列執行修改後的程式。

   ```
   python3 pubsub2.py --message "" --count 2 --topic device/+/details --ca_file ~/certs/Amazon-root-CA-1.pem --cert ~/certs/device.pem.crt --key ~/certs/private.pem.key --endpoint your-iot-endpoint
   ```

1. 在 AWS IoT 主控台中，開啟 [MQTT 測試用戶端](https://console.aws.amazon.com/iot/home#/test)。

1. 於 **Subscribe to a topic** (訂閱主題) 的 **Subscription topic** (訂閱主題) 欄位中，輸入主題篩選條件：**device/\$1/details**，再選擇 **Subscribe to topic** (訂閱主題)。

1. 在 MQTT 測試用戶端的 **Subscriptions** (訂閱) 欄中，選擇 **device/\$1/details**。

1. 若為此表格中的每個主題，請在 MQTT 測試用戶端中執行下列動作：    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/sdk-tutorials.html)

   1. 於 **Publish** (發佈) 中，輸入來自表格中 **Topic name** (主題名稱) 欄的值。

   1. 在主題名稱下方的訊息承載欄位中，輸入來自表格中 **Message payload** (訊息承載) 欄的值。

   1. 觀看 `pubsub.py` 正在執行的終端機視窗，並在 MQTT 測試用戶端中，選擇 **Publish to topic** (發佈至主題)。

   您應該看到該訊息是由終端機視窗中的 `pubsub.py` 所收到。

您應該會在終端機視窗中看到類似的內容。

```
Connecting to a3qexamplesffp-ats.iot.us-west-2.amazonaws.com with client ID 'test-af794be0-7542-45a0-b0af-0b0ea7474517'...
Connected!
Subscribing to topic 'device/+/details'...
Subscribed with QoS.AT_LEAST_ONCE
Waiting for all messages to be received...
Received message from topic 'device/light/details': b'{ "desiredLight": 100, "currentLight": 50 }'
Received light request: b'{ "desiredLight": 100, "currentLight": 50 }'
Received message from topic 'device/temp/details': b'{ "desiredTemp": 20, "currentTemp": 15 }'
Received temperature request: b'{ "desiredTemp": 20, "currentTemp": 15 }'
2 message(s) received.
Disconnecting...
Disconnected!
```

#### 演練結果
<a name="sdk-tutorials-experiment-process-result"></a>

在本練習中，您已新增程式碼，讓範例應用程式能辨識並處理回呼函數中的多個訊息。有了這個，您的裝置可以接收訊息並對其採取行動。

裝置接收和處理多則訊息的另一種方式是分別訂閱不同訊息，並將每個訂閱分配給各自的回呼函數。

### 從您的裝置發佈訊息
<a name="sdk-tutorials-experiment-publish"></a>

您可使用 pubsub.py 範例應用程式，以發佈來自您裝置的訊息。在其會發佈訊息時，這些訊息無法作為 JSON 文件加以讀取。本練習會修改範例應用程式，以便在可讀取的訊息承載中發佈 JSON 文件 AWS IoT Core。

#### 演練程序
<a name="sdk-tutorials-experiment-publish-steps"></a>

在本練習中，下列訊息將會與 `device/data` 主題一起傳送。

```
{
    "timestamp": 1601048303,
    "sensorId": 28,
    "sensorData": [
        {
        "sensorName": "Wind speed",
        "sensorValue": 34.2211224
        }
    ]
}
```

**如要準備 MQTT 測試用戶端監控本練習的訊息**

1. 於 **Subscribe to a topic** (訂閱主題) 的 **Subscription topic** (訂閱主題) 欄位中，輸入主題篩選條件：**device/data**，再選擇 **Subscribe to topic** (訂閱主題)。

1. 在 MQTT 測試用戶端的 **Subscriptions** (訂閱) 欄中，選擇 **device/data**。

1. 讓 MQTT 測試用戶端視窗保持開啟狀態，以等待來自您裝置的訊息。

**如要使用 pubsub.py 範例應用程式傳送 JSON 文件**

1. 在您的裝置上，將 `pubsub.py` 複製至 `pubsub3.py`。

1. Edit (編輯) `pubsub3.py`，變更其格式化所發佈訊息的方式。

   1. 在文字編輯器中開啟 `pubsub3.py`。

   1. 找出這行程式碼：

      `message = "{} [{}]".format(message_string, publish_count)`

   1. 將其變更為：

      `message = "{}".format(message_string)`

   1. 找出這行程式碼：

      `message_json = json.dumps(message)`

   1. 將其變更為：

      `message = "{}".json.dumps(json.loads(message))`

   1. 儲存您的變更。

1. 在您的裝置上，執行此命令以傳送訊息兩次。

   ```
   python3 pubsub3.py  --ca_file ~/certs/Amazon-root-CA-1.pem  --cert ~/certs/device.pem.crt  --key ~/certs/private.pem.key  --topic device/data  --count 2 --message '{"timestamp":1601048303,"sensorId":28,"sensorData":[{"sensorName":"Wind speed","sensorValue":34.2211224}]}'  --endpoint your-iot-endpoint
   ```

1. 於 MQTT 測試用戶端中，檢查是否已解譯並格式化訊息承載中的 JSON 文件，例如：  
![\[顯示如何在 AWS IoT 主控台的 MQTT 用戶端中顯示 JSON 訊息承載的影像。\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/images/mqtt-test-client-output.png)

依預設，`pubsub3.py` 也會訂閱其傳送的訊息。您您應會看到其在應用程式輸出中收到訊息。終端機視窗看起來與下列內容相似。

```
Connecting to a3qEXAMPLEsffp-ats.iot.us-west-2.amazonaws.com with client ID 'test-5cff18ae-1e92-4c38-a9d4-7b9771afc52f'...
Connected!
Subscribing to topic 'device/data'...
Subscribed with QoS.AT_LEAST_ONCE
Sending 2 message(s)
Publishing message to topic 'device/data': {"timestamp":1601048303,"sensorId":28,"sensorData":[{"sensorName":"Wind speed","sensorValue":34.2211224}]}
Received message from topic 'device/data': b'{"timestamp":1601048303,"sensorId":28,"sensorData":[{"sensorName":"Wind speed","sensorValue":34.2211224}]}'
Publishing message to topic 'device/data': {"timestamp":1601048303,"sensorId":28,"sensorData":[{"sensorName":"Wind speed","sensorValue":34.2211224}]}
Received message from topic 'device/data': b'{"timestamp":1601048303,"sensorId":28,"sensorData":[{"sensorName":"Wind speed","sensorValue":34.2211224}]}'
2 message(s) received.
Disconnecting...
Disconnected!
```

#### 演練結果
<a name="sdk-tutorials-experiment-publish-result"></a>

如此一來，您的裝置就可以產生要傳送至 的訊息 AWS IoT Core ，以測試基本連線，並提供裝置訊息 AWS IoT Core 讓 處理。例如，您可以使用此應用程式從您的裝置傳送測試資料，以測試 AWS IoT 規則動作。

## 檢視結果
<a name="sdk-tutorials-conclusion"></a>

本教學中的範例為您提供了有關裝置如何與 通訊的基本知識的實作體驗 AWS IoT Core，這是您 AWS IoT 解決方案的基本部分。當您的裝置能夠與 通訊時 AWS IoT Core，他們可以將訊息傳遞給 AWS 服務和其他可以採取行動的裝置。同樣地， AWS 服務和其他裝置可以處理導致訊息傳回裝置的資訊。

當您準備好 AWS IoT Core 進一步探索時，請嘗試這些教學課程：
+ [教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md)
+ [教學課程：將裝置資料儲存在 DynamoDB 表格中](iot-ddb-rule.md)
+ [教學課程：使用 AWS Lambda 函數格式化通知](iot-lambda-rule.md)

# 教學課程：使用 適用於 Embedded C 的 AWS IoT Device SDK
<a name="iot-embedded-c-sdk"></a>

本節說明如何執行 適用於 Embedded C 的 AWS IoT Device SDK。

**Topics**
+ [Step1：安裝 適用於 Embedded C 的 AWS IoT Device SDK](#install-embedded-c-sdk)
+ [步驟 2：設定範例應用程式](#iot-c-sdk-app-config)
+ [步驟 3：建置並執行範例應用程式](#iot-c-sdk-app-run)

## Step1：安裝 適用於 Embedded C 的 AWS IoT Device SDK
<a name="install-embedded-c-sdk"></a>

通常以需要最佳化 C 語言執行時間的資源限制裝置 適用於 Embedded C 的 AWS IoT Device SDK 為目標。您可以在任何作業系統上使用軟體開發套件，並將其裝載在任何處理器類型 (例如 MCU 和 MPU) 上。如果您有更多可用的記憶體和處理資源，建議您使用較高順序的裝置 AWS IoT 和行動 SDKs （例如 C\$1\$1、Java、JavaScript 和 Python)。

一般而言， 適用於 Embedded C 的 AWS IoT Device SDK 適用於使用 MCUs的系統或執行內嵌作業系統的低階 MPUs。在本節中的程式設計範例，我們假設您的裝置使用 Linux。

**Example**  

1. 從 [GitHub](https://github.com/aws/aws-iot-device-sdk-embedded-C) 將 下載 適用於 Embedded C 的 AWS IoT Device SDK 至您的裝置。

   ```
   git clone https://github.com/aws/aws-iot-device-sdk-embedded-c.git --recurse-submodules
   ```

   這會在目前目錄中建立名為 `aws-iot-device-sdk-embedded-c` 的目錄。

1. 導航至該目錄並查看最新版本。請參閱[ github.com/aws/aws-iot-device-sdk-embedded-C/tags](https://github.com/aws/aws-iot-device-sdk-embedded-C/tags)，取得最新版本標籤。

   ```
   cd aws-iot-device-sdk-embedded-c
   git checkout latest-release-tag
   ```

1. 安裝 OpenSSL 1.1.0 版或更新版本。當透過套件管理工具進行安裝時，OpenSSL 開發程式庫通常會稱為 "libssl-dev" 或 "openssl-devel"。

   ```
   sudo apt-get install libssl-dev
   ```

## 步驟 2：設定範例應用程式
<a name="iot-c-sdk-app-config"></a>

 適用於 Embedded C 的 AWS IoT Device SDK 包含供您嘗試的範例應用程式。為了簡化，本教學課程使用 `mqtt_demo_mutual_auth` 應用程式，說明如何連線至 AWS IoT Core 訊息中介裝置，以及訂閱和發佈至 MQTT 主題。

1. 將您建立於 [AWS IoT Core 教學課程入門](iot-gs.md) 中的憑證和私有金鑰複製至 `build/bin/certificates` 目錄中。
**注意**  
裝置和根憑證授權機構憑證會有過期或遭撤銷的可能。若這些憑證過期或遭到撤銷，您必須將新的憑證授權機構憑證或私有金鑰和裝置憑證複製到裝置上。

1. 您必須使用個人 AWS IoT Core 端點、私有金鑰、憑證和根 CA 憑證來設定範例。導覽至 `aws-iot-device-sdk-embedded-c/demos/mqtt/mqtt_demo_mutual_auth` 目錄。

   如果您 AWS CLI 已安裝 ，您可以使用此命令來尋找帳戶的端點 URL。

   ```
   aws iot describe-endpoint --endpoint-type iot:Data-ATS
   ```

   如果您沒有 AWS CLI 安裝 ，請開啟您的 [AWS IoT 主控台](https://console.aws.amazon.com/iot/home)。在導覽窗格中，選擇 **Manage (管理)**，然後選擇 **Things (物件)**。為您的裝置選擇 IoT 物件，然後選擇 **Interact** (互動)。您的端點會顯示在物件詳細資料頁面的 **HTTPS** 區段中。

1. 開啟 `demo_config.h` 檔案，並更新下列內容的值：  
AWS\$1IOT\$1ENDPOINT  
您的個人端點。  
CLIENT\$1CERT\$1PATH  
您的憑證檔案路徑，例如 `certificates/device.pem.crt"`。  
CLIENT\$1PRIVATE\$1KEY\$1PATH  
您的私有金鑰檔案名稱，例如`certificates/private.pem.key`。

   例如：

   ```
   // Get from demo_config.h
   // =================================================
   #define AWS_IOT_ENDPOINT               "my-endpoint-ats.iot.us-east-1.amazonaws.com"
   #define AWS_MQTT_PORT                  8883
   #define CLIENT_IDENTIFIER              "testclient"
   #define ROOT_CA_CERT_PATH              "certificates/AmazonRootCA1.crt"
   #define CLIENT_CERT_PATH               "certificates/my-device-cert.pem.crt"
   #define CLIENT_PRIVATE_KEY_PATH        "certificates/my-device-private-key.pem.key"
   // =================================================
   ```

1. 使用此命令來檢查您的裝置是否已安裝 CMake。

   ```
   cmake --version
   ```

   若您看見編譯器的版本資訊，則可繼續到下一節。

   若發生錯誤，或者沒看見資任何訊，您將需要使用此命令來安裝 cmake 套件。

   ```
   sudo apt-get install cmake
   ```

   再次執行 **cmake --version** 命令，確認已安裝 CMake，備妥繼續。

1. 使用此命令來檢查您的裝置是否已安裝開發工具。

   ```
   gcc --version
   ```

   若您看見編譯器的版本資訊，則可繼續到下一節。

   如果發生錯誤，或者沒看見編譯器資訊，您將需要使用此命令來安裝 `build-essential` 套件。

   ```
   sudo apt-get install build-essential
   ```

   再次執行 **gcc --version** 命令，確認已安裝建置工具，準備好繼續。

## 步驟 3：建置並執行範例應用程式
<a name="iot-c-sdk-app-run"></a>

此程序說明如何在您的裝置上產生`mqtt_demo_mutual_auth`應用程式，並使用 將其連接至[AWS IoT 主控台](https://console.aws.amazon.com/iot/home) 適用於 Embedded C 的 AWS IoT Device SDK。

**執行 適用於 Embedded C 的 AWS IoT Device SDK 範例應用程式**

1. 導覽至 `aws-iot-device-sdk-embedded-c`，建立一個建置目錄。

   ```
   mkdir build && cd build
   ```

1. 輸入下列 CMake 命令，產生需要建置的 Makefile。

   ```
   cmake ..  
   ```

1. 輸入下列命令來建置可執行的應用程式檔案。

   ```
   make
   ```

1. 使用此命令執行 `mqtt_demo_mutual_auth` 應用程式。

   ```
   cd bin
   ./mqtt_demo_mutual_auth
   ```

   您應該會看到類似下列的輸出：  
![\[執行 適用於 Embedded C 的 AWS IoT Device SDK 範例應用程式的命令列輸出。\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/images/successful-run2.png)

您的裝置現在已 AWS IoT 使用 連線至 適用於 Embedded C 的 AWS IoT Device SDK。

您也可以使用 AWS IoT 主控台來檢視範例應用程式正在發佈的 MQTT 訊息。如需關於如何在 [AWS IoT 主控台](https://console.aws.amazon.com/iot/home)中使用 MQTT 用戶端的資訊，請參閱 [使用 MQTT 用戶端檢視 AWS IoT MQTT 訊息](view-mqtt-messages.md)。

# 建立 AWS IoT 規則將裝置資料路由到其他 服務
<a name="iot-rules-tutorial"></a>

這些教學課程說明如何使用一些較常見的 AWS IoT 規則動作來建立和測試規則。

AWS IoT 規則會將資料從您的裝置傳送至其他 AWS 服務。其會聆聽特定的 MQTT 訊息、格式化訊息承載中的資料，並將結果傳送至其他 AWS 服務。

即使目標是要建立使用 Lambda 函數或更複雜的規則，我們仍建議您依照此處顯示的順序進行嘗試。教學課程會依照基本到複雜的順序顯示。其會逐步提供新概念，協助您學習可用來建立沒有特定教學課程的規則動作概念。

**注意**  
AWS IoT 規則可協助您將資料從 IoT 裝置傳送至其他 AWS 服務。不過，如要成功地達到這一點，您需具備要傳送資料的其他服務的相關工作知識。雖然這些教學課程提供了完成任務所需的資訊，但您可能會發現，在解決方案中使用這些服務之前，進一步了解將資料傳送至服務的相關資訊可能更有幫助。其他服務的詳細說明 AWS 超出這些教學課程的範圍。

**教學課程方案概觀**  
這些教學課程的方案為定期發佈其資料的天氣感應器裝置。在此虛構的系統中有很多這樣的感應器裝置。不過，本節中的教學課程會聚焦在單一裝置上，同時展現容納多個感應器的方法。

本節中的教學課程說明如何使用 AWS IoT 規則，透過這個假想的天氣感應器裝置系統來執行下列任務。
+ 

**[教學課程：重新發佈 MQTT 訊息](iot-repub-rule.md)**  
本教學課程將會顯示如何將氣象感應器所接收的 MQTT 訊息重新發佈為僅包含感應器 ID 和溫度值的訊息。其僅使用 AWS IoT Core 服務，並展示簡單的 SQL 查詢，及如何使用 MQTT 用戶端來測試您的規則。
+ 

**[教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md)**  
本教學課程會顯示天氣感應器裝置的值超出特定值時，如何傳送 SNS 訊息。它以先前教學課程中呈現的概念為基礎，並新增了如何使用其他服務 AWS ：[Amazon Simple Notification Service](https://docs.aws.amazon.com//sns/latest/dg/welcome.html) (Amazon SNS)。

  若您初次使用 Amazon SNS，請檢閱其[入門](https://docs.aws.amazon.com//sns/latest/dg/sns-getting-started.html)練習，然後再開始本教學課程。
+ 

**[教學課程：將裝置資料儲存在 DynamoDB 表格中](iot-ddb-rule.md)**  
本教學課程會顯示如何從天氣感應器裝置存放資料庫表中的資料。其會使用規則查詢陳述式和替代範本來格式化目的地服務[Amazon DynamoDB](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/Introduction.html) 的訊息資料。

  若您初次使用 DynamoDB，請檢閱其[入門](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html)練習，然後再開始本教學課程。
+ 

**[教學課程：使用 AWS Lambda 函數格式化通知](iot-lambda-rule.md)**  
本教學課程顯示如何呼叫 Lambda 函數來重新格式化裝置資料，然後以文字訊息進行傳送。它會在 [AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html)函數中新增 Python 指令碼和 AWS SDK 函數，以格式化來自天氣感應器裝置的訊息承載資料，並傳送文字訊息。

  若您初次使用 Lambda，請檢閱其[入門](https://docs.aws.amazon.com//lambda/latest/dg/getting-started.html)練習，然後再開始本教學課程。

**AWS IoT 規則概觀**  
所有這些教學課程都會建立 AWS IoT 規則。

若要讓 AWS IoT 規則將資料從裝置傳送至其他服務 AWS ，它會使用：


+ 包含下列項目的規則查詢陳述式：
  + SQL SELECT 子句，用於選取並格式化訊息承載中的資料
  + 主題篩選條件 (規則查詢陳述式中的 FROM 物件)，用來識別要使用的訊息
  + 選用性的條件陳述式 (SQL WHERE 子句)，指定要採取行動的特定條件
+ 至少一個規則動作

裝置會發佈訊息至 MQTT 主題。SQL SELECT 陳述式中的主題篩選條件會識別要套用規則的 MQTT 主題。SQL SELECT 陳述式中指定的欄位會格式化傳入 MQTT 訊息承載的資料，以供規則動作使用。如需規則動作的完整清單，請參閱 [AWS IoT 規則動作](iot-rule-actions.md)。

**Topics**
+ [教學課程：重新發佈 MQTT 訊息](iot-repub-rule.md)
+ [教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md)
+ [教學課程：將裝置資料儲存在 DynamoDB 表格中](iot-ddb-rule.md)
+ [教學課程：使用 AWS Lambda 函數格式化通知](iot-lambda-rule.md)

# 教學課程：重新發佈 MQTT 訊息
<a name="iot-repub-rule"></a>

本教學課程示範如何建立 AWS IoT 規則，在接收到指定的 MQTT 訊息時發佈 MQTT 訊息。傳入的訊息承載可在發佈前由規則進行修改。這樣就可以建立專為特定應用程式量身訂製的訊息，而不需要更改裝置或其韌體。您還可使用規則的篩選條件面向，僅在符合特定條件時才發佈訊息。

規則重新發佈的訊息就像由任何其他 AWS IoT 裝置或用戶端傳送的訊息。裝置可訂閱重新發佈的訊息，就像裝置可訂閱任何其他 MQTT 訊息主題一樣。

**您會在本教學課程中學到什麼：**
+ 如何在規則查詢陳述式中使用簡單的 SQL 查詢和函數
+ 如何使用 MQTT 用戶端測試 AWS IoT 規則

此教學課程約需 30 分鐘方能完成。

**Topics**
+ [檢閱 MQTT 主題和 AWS IoT 規則](#iot-repub-rule-mqtt)
+ [步驟 1：建立 AWS IoT 規則以重新發佈 MQTT 訊息](#iot-repub-rule-define)
+ [步驟 2：測試新規則](#iot-repub-rule-test)
+ [步驟 3：檢閱結果及後續步驟](#iot-repub-rule-review)

**開始本教學課程之前，請確定您有：**
+ 

**[設定 AWS 帳戶](setting-up.md)**  
您需要 AWS 帳戶 和 AWS IoT 主控台才能完成本教學課程。
+ 

**檢閱 [使用 MQTT 用戶端檢視 AWS IoT MQTT 訊息](view-mqtt-messages.md)**  
請確定您可使用 MQTT 用戶端來訂閱並發佈至主題。您會使用 MQTT 用戶端，在此程序中測試您的新規則。

## 檢閱 MQTT 主題和 AWS IoT 規則
<a name="iot-repub-rule-mqtt"></a>

在討論 AWS IoT 規則之前，了解 MQTT 通訊協定會有幫助。在 IoT 解決方案中，MQTT 通訊協定提供了一些優於其他網路通訊協定 (如 HTTP) 的優勢，這使其成為 IoT 裝置使用的熱門選擇。本節將會檢視 MQTT 適用於本教學課程的主要層面。如需 MQTT 與 HTTP 比較的資訊，請參閱 [選擇裝置通訊的應用程式通訊協定](protocols.md#protocol-selection)。

**MQTT 通訊協定**  
MQTT 通訊協定會與其主機一起使用發佈/訂閱通訊模型。若要傳送資料，裝置會將主題識別的訊息發佈至 AWS IoT 訊息中介裝置。若要收到訊息代理程式的訊息，裝置會在訂閱請求中傳送主題篩選條件給訊息代理程式，以訂閱其會收到的主題。 AWS IoT 規則引擎會收到來自訊息代理程式的 MQTT 訊息。

**AWS IoT 規則**  
AWS IoT 規則包含規則查詢陳述式和一或多個規則動作。當 AWS IoT 規則引擎收到 MQTT 訊息時，這些元素對訊息產生的作用如下。
+ 

**規則查詢陳述式**  
規則的查詢陳述式說明要使用的 MQTT 主題、解譯來自訊息承載的資料，及依據 SQL 陳述式所描述的 SQL 陳述式來格式化資料，這些陳述式類似於常用 SQL 資料庫所使用的陳述式。查詢陳述式的結果為傳送至規則動作的資料。
+ 

**規則動作**  
規則中的每個規則動作都會作用於規則查詢陳述式所產生的資料。 AWS IoT 支援[許多規則動作](iot-rule-actions.md)。不過，在本教學課程中，您會專注於 [重新發佈](republish-rule-action.md) 規則動作，其會將查詢陳述式的結果發佈為具有特定主題的 MQTT 訊息。

## 步驟 1：建立 AWS IoT 規則以重新發佈 MQTT 訊息
<a name="iot-repub-rule-define"></a>

您將在本教學課程中建立的 AWS IoT 規則會訂閱 `device/device_id/data` MQTT 主題，其中 *device\$1id* 是傳送訊息的裝置 ID。[主題篩選條件](topics.md#topicfilters)會將這些主題描述為 `device/+/data`，其中`+` 為與兩個正斜線字元間之任何字串相符的萬用字元。

規則收到來自相符主題的訊息時，其會重新發佈 `device_id` 和 `temperature` 值，作為具 `device/data/temp` 主題的新 MQTT 訊息。

例如，具 `device/22/data` 主題的 MQTT 訊息承載如下所示：

```
{
  "temperature": 28,
  "humidity": 80,
  "barometer": 1013,
  "wind": {
    "velocity": 22,
    "bearing": 255
  }
}
```

該規則採用來自訊息承載的 `temperature` 值及來自主題的 `device_id`，並將其重新發佈為具 `device/data/temp` 主題的 MQTT 訊息，及如下所示的訊息承載：

```
{
  "device_id": "22",
  "temperature": 28
}
```

使用此規則，則只需要裝置 ID 和溫度資料的裝置會訂閱 `device/data/temp` 主題，以僅接收該資訊。

**如要建立一個重新發佈 MQTT 訊息的規則**

1. 開啟 [AWS IoT 主控台的**規則**中樞](https://console.aws.amazon.com//iot/home#/rulehub)。

1. 在 **Rules** (規則) 中，選擇**Create**(建立)，然後開始建立新規則。

1. 在 **Create a rule** (建立規則) 的頂部中：

   1. 在 **Name** (名稱) 中，輸入規則的名稱。在本教學課程中，請將其命名為 **republish\$1temp**。

      請記住，規則名稱在您的帳戶和區域內必須是唯一的，且不能有任何空格。我們在此名稱中使用底線字元來分隔規則名稱中的兩個單字。

   1.  在 **Description** (說明) 中，說明規則。

      有意義的說明可幫助您記住此規則的作用及建立規則的原因。說明可依所需而定，因此請盡可能詳細說明。

1. 在 **Create a rule** (建立規則) 的 **Rule query statement** (規則查詢陳述式) 中：

   1.  在**使用 SQL 版本**中，選取 **2016-03-23**。

   1. 在 **Rule query statement** (規則查詢陳述式) 編輯方塊中輸入陳述式：

      ```
      SELECT topic(2) as device_id, temperature FROM 'device/+/data'
      ```

      本陳述式：
      + 聆聽具與 `device/+/data` 主題篩選條件相符之主題的 MQTT 訊息。
      + 從主題字串中選取第二個元素，並將其指定給 `device_id` 欄位。
      + 從訊息承載選取值 `temperature` 欄位，並將其指派給 `temperature` 欄位。

1. 在 **Set one or more actions** (設定一個或多個動作) 中：

   1. 若要開啟此規則的規則動作清單，請選擇 **Add action** (新增動作)。

   1. 在**選取動作**中，選擇**重新發佈訊息至 AWS IoT 主題**。

   1. 在動作清單底部，選擇**設定動作**以開啟所選動作的組態頁面。

1. 在 **Configure action** (設定動作)：

   1.  在 **Topic** (主題) 中，輸入 **device/data/temp**。這是此規則將發佈訊息的 MQTT 主題。

   1.  在**Quality of Service** (服務品質) 中，選擇 **0 - The message is delivered zero or more times** (0 - 訊息傳遞零次或多次)。

   1.  在**選擇或建立角色以授予執行此動作的 AWS IoT 存取權**：

      1.  選擇 **Create Role** (建立角色)。**Create a new role** (建立新角色) 對話方塊隨即開啟。

      1. 輸入可說明新角色的名稱。在本教學課程中，使用 **republish\$1role**。

         當您建立新角色時，會建立執行規則動作的正確政策，並將其連接至新角色。如果您變更此規則動作的主題，或在其他規則動作中使用此角色，則必須更新該角色的政策，以授權新的主題或動作。若要更新現有角色，請選擇本節中的 **Update role** (更新角色)。

      1. 選擇**Create Role** (建立角色)，以建立角色並關閉對話方塊。

   1. 選擇**Add action** (新增動作)，將動作新增至規則，並返回**Create a rule** (建立規則) 頁面。

1. 將**訊息重新發佈至 AWS IoT 主題**動作現在列在**設定一或多個動作**中。

   在新動作的圖標中，**Republish a message to an AWS IoT topic (將訊息重新發佈至 IoT 主題)** 之下，您可看到重新發佈動作將發佈的主題。

   這是您將新增至此規則的唯一規則動作。

1. 在 **Create a rule** (建立規則) 中，向下捲動至底部，然後選擇 **Create rule** (建立規則)，建立規則並完成此步驟。

## 步驟 2：測試新規則
<a name="iot-repub-rule-test"></a>

若要測試新規則，您將使用 MQTT 用戶端來發佈和訂閱此規則所使用的 MQTT 訊息。

在新視窗的 [AWS IoT 主控台中開啟 MQTT 用戶端](https://console.aws.amazon.com//iot/home#/test)。這可讓您編輯規則，而不會遺失 MQTT 用戶端的組態。如果您讓它轉到主控台中的另一個頁面，MQTT 用戶端不會保留任何訂閱或訊息記錄。

**如要使用 MQTT 用戶端來測試您的規則。**

1. 在 AWS IoT 主控台的 [MQTT 用戶端](https://console.aws.amazon.com//iot/home#/test) 中，訂閱輸入主題，在此案例中為 `device/+/data`。

   1. 在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下選擇 **Subscribe to a topic** (訂閱主題)。

   1. 在 **Subscription topic** (訂閱主題) 中，輸入輸入主題篩選條件 **device/\$1/data** 的主題 。

   1. 將剩下的欄位保留為其預設設定。

   1. 請選擇 **Subscribe to topic** (訂閱主題)。

      在 **Subscriptions** (訂閱) 欄中，**Publish to a topic** (發佈到主題) 之下，**device/\$1/data** 隨即顯示。

1. 訂閱規則將發佈的主題：`device/data/temp`。

   1. 在 **Subscriptions** (訂閱) 之下，選擇 **Subscribe to a topic** (訂閱主題)，並在 **Subscription topic** (訂閱主題) 中，輸入重新發佈訊息 **device/data/temp** 的主題。

   1. 將剩下的欄位保留為其預設設定。

   1. 請選擇 **Subscribe to topic** (訂閱主題)。

      在 **Subscriptions** (訂閱) 欄中，**device/\$1/data** 之下，**device/data/temp** 隨即顯示。

1. 使用特定裝置 ID **device/22/data**，將訊息發佈至輸入主題。您無法發佈至包含萬用字元的 MQTT 主題。

   1. 在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下選擇 **Publish to topic** (發佈至主題)。

   1. 在 **Publish** (發佈) 欄位中輸入輸入主題名稱 **device/22/data**。

   1. 複製此處顯示的範例資料，並在主題名稱下方的編輯方塊中貼上範例資料。

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. 若要傳送 MQTT 訊息，請選擇 **Publish to topic** (發佈至主題)。

1. 檢閱傳送的訊息。

   1. 在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下，您先前訂閱的兩個主題旁會有一個綠點。

      該綠點表示自上次查看後，已收到一個或多個新訊息。

   1. 於 **Subscriptions** (訂閱) 下，選擇 **device/\$1/data**，來檢查訊息承載是否與您剛剛發佈的內容相符，如下所示：

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. 於 **Subscriptions** (訂閱) 下，選擇 **device/data/temp**，來檢查您重新發佈的訊息承載，如下所示：

      ```
      {
        "device_id": "22",  
        "temperature": 28
      }
      ```

      請注意，`device_id` 值是個帶有引號的字串，而 `temperature` 值是個數字。這是因為 [https://docs.aws.amazon.com//iot/latest/developerguide/iot-sql-functions.html#iot-function-topic](https://docs.aws.amazon.com//iot/latest/developerguide/iot-sql-functions.html#iot-function-topic) 函數從輸入訊息的主題名稱中提取字串，而 `temperature` 值會使用輸入訊息承載的數值。

      若要將 `device_id` 值設為數值，請將規則查詢陳述式中的 `topic(2)` 替換為：

      ```
      cast(topic(2) AS DECIMAL)
      ```

      請注意，將 `topic(2)` 值轉換為數值，僅適用於主題的該部分僅包含數字字元時。

1. 若您看到正確的訊息已發佈至 **device/data/temp** 主題，則您的規則有效。請參閱下一節，了解更多 Republish (重新發佈) 規則動作的相關資訊。

   若您看不到正確的訊息已發佈至 **device/\$1/data** 或 **device/data/temp** 主題中，請查看疑難排解提示。

### 疑難排解重新發佈訊息規則
<a name="iot-repub-rule-trouble"></a>

若您並未看到預期的結果，請查看以下事項。
+ 

**您收到錯誤的橫幅**  
若在您發佈輸入訊息時出現錯誤，請先更正該錯誤。下列步驟可協助您修正該錯誤。
+ 

**您並未在 MQTT 用戶端中看到輸入訊息**  
每次您將輸入訊息發佈至 `device/22/data` 主題時，若您依程序中所述訂閱了 `device/+/data` 主題篩選條件，則該訊息應會顯示於 MQTT 用戶端中。

**要檢查的事項**
  + 

**檢查您訂閱的主題篩選條件**  
若您依程序中所述訂閱了輸入訊息主題，則每次發佈輸入訊息時都應該會看到其複本。

    若您並未訊息，請檢查您訂閱的主題名稱，並將其與所發佈的主題進行比較。主題名稱區分大小寫，且您訂閱的主題必須與所發佈訊息承載的主題相同。
  + 

**檢查訊息發佈功能**  
在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下，選擇 **device/\$1/data**，檢查發佈訊息的主題，然後選擇 **Publish to topic** (發佈至主題)。您應該會在訊息清單中出現主題下方的編輯方塊中看到訊息承載。
+ 

**您在 MQTT 用戶端中並未看到已重新發佈的訊息**  
若要讓您的規則運作，其必須具有授權其接收和重新發佈訊息的正確政策，且必須接收訊息。

**要檢查的事項**
  + 

**檢查 MQTT 用戶端 AWS 區域 的 和您建立的規則**  
您正在執行 MQTT 用戶端的主控台必須與您建立的規則處於相同的 AWS 區域。
  + 

**檢查規則查詢陳述式中的輸入訊息主題**  
若要讓規則運作，其必須收到一則訊息，其主題名稱與規則查詢陳述式之 FROM 子句中的主題篩選條件相符。

    檢查規則查詢陳述式中主題篩選條件的拼字與 MQTT 用戶端中主題的拼字。主題名稱區分大小寫，且郵件的主題必須與規則查詢陳述式中的主題篩選條件相符。
  + 

**檢查輸入訊息承載的內容**  
若要讓規則運作，其必須在 SELECT 陳述式中宣告的訊息承載中尋找資料欄位。

    檢查規則查詢陳述式中 `temperature` 欄位的拼字與 MQTT 用戶端中訊息承載的拼字。欄位名稱區分大小寫，規則查詢陳述式中的 `temperature` 欄位必須與訊息承載中的 `temperature` 欄位相符。

    請確定訊息承載中的 JSON 文件格式正確。若 JSON 有任何錯誤，例如缺少逗號，則規則將無法進行讀取。
  + 

**檢查規則動作中重新發佈的訊息主題**  
Republish (重新發佈) 規則動作發佈新訊息的主題必須與您在 MQTT 用戶端中訂閱的主題相符。

    開啟您建立於主控台中的規則，並檢查規則動作重新發佈訊息的主題。
  + 

**檢查規則所使用的角色**  
規則動作必須具有接收原始主題及發佈新主題的權限。

    授權規則接收訊息資料的政策並加以重新發佈為所使用的主題所特定的。若變更用於重新發佈訊息資料的主題，則必須更新規則動作的角色，來更新其政策以與目前主題相符。

    若您懷疑這會是問題，請編輯 Republish (重新發佈) 規則動作並建立新角色。規則動作建立的新角色會收到執行這些動作所需的授權。

## 步驟 3：檢閱結果及後續步驟
<a name="iot-repub-rule-review"></a>

**於本教學課程中**
+ 您使用了簡單的 SQL 查詢和規則查詢陳述式中的幾個函數來產生一個新的 MQTT 訊息。
+ 您已建立一個重新發佈該新訊息的規則。
+ 您使用 MQTT 用戶端來測試 AWS IoT 規則。

**後續步驟**  
使用此規則重新發佈一些訊息之後，請嘗試使用其來查看教學課程的某些層面如何影響重新發佈的訊息。此處有幾種簡單的入門方式。
+ 變更輸入訊息主題中的 *device\$1id*，並觀察重新發佈之訊息承載中的影響。
+ 變更規則查詢陳述式中所選取的欄位，並觀察重新發佈之訊息承載中的影響。
+ 請嘗試本系列中的下一個教學課程，並了解如何進行 [教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md)。

此教學課程中所使用的 Republish (重新發佈) 規則動作亦可協助您對規則查詢陳述式進行偵錯。例如，您可將此動作新增至規則，以查看其規則查詢陳述式如何格式化用於其規則動作的資料。

# 教學課程：傳送 Amazon SNS 通知
<a name="iot-sns-rule"></a>

本教學課程示範如何建立 AWS IoT 規則，將 MQTT 訊息資料傳送至 Amazon SNS 主題，以做為 SMS 文字訊息傳送。

在本教學課程中，您會建立一個規則，在溫度超過規則中所設定的值時，將訊息資料從天氣感應器傳送至 Amazon SNS 主題的所有訂閱者。該規則會在回報的溫度超過規則設定值時進行偵測，然後建立新的訊息承載資料，其中僅包含裝置 ID、回報的溫度及超過的溫度限制。該規則會將新訊息承載作為 JSON 文件傳送至 SNS 主題，其會通知 SNS 主題的所有訂閱者。

**您會在本教學課程中學到什麼：**
+ 如何建立及測試 Amazon SNS 通知
+ 如何從 AWS IoT 規則呼叫 Amazon SNS 通知
+ 如何在規則查詢陳述式中使用簡單的 SQL 查詢和函數
+ 如何使用 MQTT 用戶端測試 AWS IoT 規則

此教學課程約需 30 分鐘方能完成。

**Topics**
+ [步驟 1：建立傳送簡訊的 Amazon SNS 主題](#iot-sns-rule-create-sns-topic)
+ [步驟 2：建立 AWS IoT 規則以傳送文字訊息](#iot-sns-rule-create-rule)
+ [步驟 3：測試 AWS IoT 規則和 Amazon SNS 通知](#iot-sns-rule-test-rule)
+ [步驟 4：檢閱結果及後續步驟](#iot-sns-rule-review-results)

**開始本教學課程之前，請確定您有：**
+ 

**[設定 AWS 帳戶](setting-up.md)**  
您需要 AWS 帳戶 和 AWS IoT 主控台才能完成本教學課程。
+ 

**檢閱 [使用 MQTT 用戶端檢視 AWS IoT MQTT 訊息](view-mqtt-messages.md)**  
請確定您可使用 MQTT 用戶端來訂閱並發佈至主題。您會使用 MQTT 用戶端，在此程序中測試您的新規則。
+ 

**檢閱 [Amazon Simple Notification Service](https://docs.aws.amazon.com//sns/latest/dg/welcome.html)**  
若您未曾使用過 Amazon SNS，請查閱[設定 Amazon SNS 的存取](https://docs.aws.amazon.com//sns/latest/dg/sns-setting-up.html)。如果您已完成其他 AWS IoT 教學課程，則應該已正確設定您的 AWS 帳戶 。

## 步驟 1：建立傳送簡訊的 Amazon SNS 主題
<a name="iot-sns-rule-create-sns-topic"></a>

此程序說明如何建立天氣感應器可以傳送訊息資料的 Amazon SNS 主題。然後，Amazon SNS 主題會透過簡訊通知所有訂閱者超過溫度限制。

**若要建立一個傳送 SMS 簡訊的 Amazon SNS 主題**

1. **建立一個 Amazon SNS 主題。**

   1. 登入 [Amazon SNS 主控台](https://console.aws.amazon.com//sns/home)。

   1. 在左側導覽窗格中，選擇 **Topics** (主題)。

   1. 在 **Topics** (主題) 頁面上，選擇 **Create new topic** (建立新主題)。

   1. 於 **Details** (詳細資訊) 中，選擇 **Standard** (標準) 類型。依預設，主控台會建立一個 FIFO 主題。

   1. 於 **Name** (名稱) 中，輸入 SNS 主題名稱。針對本教學，輸入 **high\$1temp\$1notice**。

   1. 向下捲動到頁面底部，並選擇 **Create topic** (建立主題)。

      主控台會開啟新主題的 **Details** (詳細資訊) 頁面。

1. **建立 Amazon SNS 訂閱。**
**注意**  
您在此訂閱中使用的電話號碼可能會因您將在本教學課程中傳送訊息而產生簡訊費用。

   1. 於 **high\$1temp\$1notice** 主題詳細資訊頁面中，選擇 **Create subscription** (建立訂閱)。

   1. 於**Create subscription** (建立訂閱) 的 **Details** (詳細資訊) 區段下，在 **Protocol** (通訊協定) 清單中選擇 **SMS**。

   1. 於 **Endpoint** (端點) 中，輸入可接收簡訊的電話號碼。請務必將其輸入，使其以 `+` 開頭，包含國碼和地區碼，且不包含任何其他標點符號字元。

   1. 選擇**建立訂閱**。

1. **測試 Amazon SNS 通知。**

   1. 於 [Amazon SNS 主控台](https://console.aws.amazon.com//sns/home)的左側導覽窗格中，選擇 **Topics** (主題)。

   1. 若要開啟主題的詳細資料頁面，請於 **Topics** (主題) 的主題清單中，選擇 **high\$1temp\$1notice**。

   1. 如要開啟 **Publish message to topic** (將訊息發佈至主題) 頁面，請於 **high\$1temp\$1notice** 詳細資訊頁面中，選擇 **Publish message** (發佈訊息)。

   1. 在 **Publish message to topic** (將訊息發佈至主題) 的 **Message body** (訊息內文) 區段下，在 **Message body to send to the endpoint** (要傳送至端點的訊息內文) 中，輸入簡短訊息。

   1. 捲動到頁面底部，並選擇 **Publish message** (發佈訊息)。

   1. 在您先前建立訂閱時所使用的手機號碼上，確認已收到訊息。

   若您並未收到測試訊息，請再次檢查電話號碼及手機設定。

   請確保您可從 [Amazon SNS 主控台](https://console.aws.amazon.com//sns/home) 發佈測試訊息，然後再繼續教學課程。

## 步驟 2：建立 AWS IoT 規則以傳送文字訊息
<a name="iot-sns-rule-create-rule"></a>

您將在本教學課程中建立的 AWS IoT 規則會訂閱 `device/device_id/data` MQTT 主題，其中 `device_id`是傳送訊息的裝置 ID。主題篩選條件會將這些主題描述為 `device/+/data`，其中 `+` 為與兩個正斜線字元間之任何字串相符的萬用字元。此規則也會測試訊息裝載中的 `temperature` 欄位值。

當規則收到來自相符主題的訊息時，其會採用來自主題名稱的 `device_id`、來自訊息承載的 `temperature` 值、及為其測試的限制新增一個常數值，並將這些值做為 JSON 文件傳送至 Amazon SNS 通知主題。

 例如，來自天氣感應器裝置編號 32 的 MQTT 訊息會使用 `device/32/data` 主題，並具有看起來如下的訊息承載：

```
{
  "temperature": 38,
  "humidity": 80,
  "barometer": 1013,
  "wind": {
    "velocity": 22,
    "bearing": 255
  }
}
```

規則的規則查詢陳述式採用訊息承載的 `temperature` 值、主題名稱的 `device_id`，並新增常數 `max_temperature` 值，以將看起來像這樣的訊息承載傳送至 Amazon SNS 主題：

```
{
  "device_id": "32",
  "reported_temperature": 38,
  "max_temperature": 30
}
```

**建立 AWS IoT 規則以偵測超額溫度值，並建立要傳送至 Amazon SNS 主題的資料**

1. 開啟 [AWS IoT 主控台的**規則**中樞](https://console.aws.amazon.com//iot/home#/rulehub)。

1. 若此為您的第一個規則，請選擇 **Create** (建立) 或 **Create a rule** (建立規則)。

1. 在 **Create a rule** (建立規則) 中：

   1. 在 **Name** (名稱) 中，輸入 **temp\$1limit\$1notify**。

      請記住，規則名稱在您的 AWS 帳戶 和 區域中必須是唯一的，而且不能有任何空格。我們在此名稱中使用底線字元來分隔規則名稱中的字詞。

   1. 在 **Description** (說明) 中，說明規則。

      有意義的說明可讓您更容易記住此規則的作用及您建立規則的原因。說明可依所需而定，因此請盡可能詳細說明。

1. 在 **Create a rule** (建立規則) 的 **Rule query statement** (規則查詢陳述式) 中：

   1.  在**使用 SQL 版本**中，選取 **2016-03-23**。

   1. 在 **Rule query statement** (規則查詢陳述式) 編輯方塊中輸入陳述式：

      ```
      SELECT topic(2) as device_id, 
          temperature as reported_temperature, 
          30 as max_temperature 
        FROM 'device/+/data' 
        WHERE temperature > 30
      ```

      本陳述式：
      + 聆聽主題與 `device/+/data` 主題篩選條件相符及 `temperature` 值大於 30 的 MQTT 訊息。
      + 從主題字串中選取第二個元素，並將其指定給 `device_id` 欄位。
      + 從訊息承載選取值 `temperature` 欄位，並將其指派給 `reported_temperature` 欄位。
      + 建立常數值 `30` 來表示限制值，並將其指定給 `max_temperature` 欄位。

1. 若要開啟此規則的規則動作清單，請於 **Set one or more actions** (設定一個或多個動作) 中，選擇 **Add action** (新增動作)。

1. 在 **Select an action** (選取動作) 中，選擇 **Send a message as an SNS push notification** (傳送 SNS 推送通知形式的訊息)。

1. 若要開啟所選取動作的組態頁面，請在動作清單底部選擇 **Configure action** (設定動作)。

1. 於 **Configure action** (設定動作)：

   1. 於 **SNS target** (SNS 目標) 中，選擇 **Select** (選取)，找出您名為 **high\$1temp\$1notice** 的 SNS 主題，然後選擇 **Select** (選取)。

   1. 在 **Message format** (訊息格式) 中，選擇 **RAW**。

   1. 在**選擇或建立角色以授予執行此動作的 AWS IoT 存取權**中，選擇**建立角色**。

   1. 在 **Create a new role** (建立新角色) 的 **Name** (名稱) 中，輸入新角色的唯一名稱。在本教學課程中，使用 **sns\$1rule\$1role**。

   1. 選擇 **Create Role** (建立角色)。

   若您要重複此教學課程或重複使用現有的角色，請先選擇 **Update role** (更新角色)，再繼續進行。此會更新角色的政策文件，以使用 SNS 目標。

1. 選擇 **Add action** (新增動作)，並返回 **Create a rule** (建立規則) 頁面。

   在新動作的圖標中，**Send a message as an SNS push notification** (以 SNS 推送通知形式傳送訊息)，您可看到規則呼叫的 SNS 主題。

   這是您將新增至此規則的唯一規則動作。

1. 如要建立並完成此步驟，請於 **Create a rule** (建立規則) 中，向下捲動至底部，然後選擇 **Create rule** (建立規則)。

## 步驟 3：測試 AWS IoT 規則和 Amazon SNS 通知
<a name="iot-sns-rule-test-rule"></a>

若要測試新規則，您將使用 MQTT 用戶端來發佈和訂閱此規則所使用的 MQTT 訊息。

在新視窗的 [AWS IoT 主控台中開啟 MQTT 用戶端](https://console.aws.amazon.com//iot/home#/test)。這可讓您編輯規則，而不會遺失 MQTT 用戶端的組態。如果您讓 MQTT 用戶端前往主控台中的另一個頁面，其不會保留任何訂閱或訊息記錄。

**如要使用 MQTT 用戶端來測試您的規則。**

1. 在 AWS IoT 主控台的 [MQTT 用戶端](https://console.aws.amazon.com//iot/home#/test) 中，訂閱輸入主題，在此案例中為 `device/+/data`。

   1. 在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下選擇 **Subscribe to a topic** (訂閱主題)。

   1. 在 **Subscription topic** (訂閱主題) 中，輸入輸入主題篩選條件 **device/\$1/data** 的主題 。

   1. 將剩下的欄位保留為其預設設定。

   1. 請選擇 **Subscribe to topic** (訂閱主題)。

      在 **Subscriptions** (訂閱) 欄中，**Publish to a topic** (發佈到主題) 之下，**device/\$1/data** 隨即顯示。

1. 使用特定裝置 ID **device/32/data**，將訊息發佈至輸入主題。您無法發佈至包含萬用字元的 MQTT 主題。

   1. 在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下選擇 **Publish to topic** (發佈至主題)。

   1. 在 **Publish** (發佈) 欄位中輸入輸入主題名稱 **device/32/data**。

   1. 複製此處顯示的範例資料，並在主題名稱下方的編輯方塊中貼上範例資料。

      ```
      {
        "temperature": 38,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. 選擇 **Publish to topic** (發佈至主題)，發佈您的 MQTT 訊息。

1. 確認簡訊已傳送。

   1. 在 MQTT 用戶端中 **Subscriptions** (訂閱) 下，您先前訂閱的主題旁會有一個綠點。

      該綠點表示自上次查看後，已收到一個或多個新訊息。

   1. 於 **Subscriptions** (訂閱) 下，選擇 **device/\$1/data**，來檢查訊息承載是否與您剛剛發佈的內容相符，如下所示：

      ```
      {
        "temperature": 38,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. 檢查您用來訂閱 SNS 主題的手機，並確認訊息承載內容如下所示：

      ```
      {"device_id":"32","reported_temperature":38,"max_temperature":30}
      ```

      請注意，`device_id` 值是個帶有引號的字串，而 `temperature` 值是個數字。這是因為 [https://docs.aws.amazon.com//iot/latest/developerguide/iot-sql-functions.html#iot-function-topic](https://docs.aws.amazon.com//iot/latest/developerguide/iot-sql-functions.html#iot-function-topic) 函數從輸入訊息的主題名稱中提取字串，而 `temperature` 值會使用輸入訊息承載的數值。

      若要將 `device_id` 值設為數值，請將規則查詢陳述式中的 `topic(2)` 替換為：

      ```
      cast(topic(2) AS DECIMAL)
      ```

      請注意，將 `topic(2)` 值轉換為數值，`DECIMAL` 值僅適用於該部分主題僅包含數字字元時。

1. 請嘗試傳送溫度不超過限制的 MQTT 訊息。

   1. 在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下選擇 **Publish to topic** (發佈至主題)。

   1. 在 **Publish** (發佈) 欄位中輸入輸入主題名稱 **device/33/data**。

   1. 複製此處顯示的範例資料，並在主題名稱下方的編輯方塊中貼上範例資料。

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. 若要傳送 MQTT 訊息，請選擇 **Publish to topic** (發佈至主題)。

   您應該能看到您在 **device/\$1/data** 訂閱中傳送的訊息。不過，因溫度值低於規則查詢陳述式中的最高溫度，所以您不應收到簡訊。

   若您並未看到正確的行為，請查看疑難排解提示。

### 疑難排解 SNS 訊息規則
<a name="iot-sns-rule-trouble"></a>

若您並未看到預期的結果，請查看以下事項。
+ 

**您收到錯誤的橫幅**  
若在您發佈輸入訊息時出現錯誤，請先更正該錯誤。下列步驟可協助您修正該錯誤。
+ 

**您並未在 MQTT 用戶端中看到輸入訊息**  
每次您將輸入訊息發佈至 `device/22/data` 主題中，若您依程序中所述訂閱了 `device/+/data` 主題篩選條件，則該訊息應會顯示於 MQTT 用戶端中。

**要檢查的事項**
  + 

**檢查您訂閱的主題篩選條件**  
若您依程序中所述訂閱了輸入訊息主題，則每次發佈輸入訊息時都應該會看到其複本。

    若您並未訊息，請檢查您訂閱的主題名稱，並將其與所發佈的主題進行比較。主題名稱區分大小寫，且您訂閱的主題必須與所發佈訊息承載的主題相同。
  + 

**檢查訊息發佈功能**  
在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下，選擇 **device/\$1/data**，檢查發佈訊息的主題，然後選擇 **Publish to topic** (發佈至主題)。您應該會在訊息清單中出現主題下方的編輯方塊中看到訊息承載。
+ 

**您並未收到 SMS 訊息：**  
若要讓您的規則運作，其必須具有授權其接收訊息和傳送 SNS 通知的正確政策，且必須接收訊息。

**要檢查的事項**
  + 

**檢查 MQTT 用戶端 AWS 區域 的 和您建立的規則**  
您正在執行 MQTT 用戶端的主控台必須與您建立的規則處於相同的 AWS 區域。
  + 

**檢查訊息承載中的溫度值是否超過測試閾值**  
若溫度值小於或等於 30 (如規則查詢陳述式中所定義)，則規則將不會執行其任何動作。
  + 

**檢查規則查詢陳述式中的輸入訊息主題**  
若要讓規則運作，其必須收到一則訊息，其主題名稱與規則查詢陳述式之 FROM 子句中的主題篩選條件相符。

    檢查規則查詢陳述式中主題篩選條件的拼字與 MQTT 用戶端中主題的拼字。主題名稱區分大小寫，且郵件的主題必須與規則查詢陳述式中的主題篩選條件相符。
  + 

**檢查輸入訊息承載的內容**  
若要讓規則運作，其必須在 SELECT 陳述式中宣告的訊息承載中尋找資料欄位。

    檢查規則查詢陳述式中 `temperature` 欄位的拼字與 MQTT 用戶端中訊息承載的拼字。欄位名稱區分大小寫，規則查詢陳述式中的 `temperature` 欄位必須與訊息承載中的 `temperature` 欄位相符。

    請確定訊息承載中的 JSON 文件格式正確。若 JSON 有任何錯誤，例如缺少逗號，則規則將無法進行讀取。
  + 

**檢查規則動作中重新發佈的訊息主題**  
Republish (重新發佈) 規則動作發佈新訊息的主題必須與您在 MQTT 用戶端中訂閱的主題相符。

    開啟您建立於主控台中的規則，並檢查規則動作重新發佈訊息的主題。
  + 

**檢查規則所使用的角色**  
規則動作必須具有接收原始主題及發佈新主題的權限。

    授權規則接收訊息資料的政策並加以重新發佈為所使用的主題所特定的。若變更用於重新發佈訊息資料的主題，則必須更新規則動作的角色，來更新其政策以與目前主題相符。

    若您懷疑這會是問題，請編輯 Republish (重新發佈) 規則動作並建立新角色。規則動作建立的新角色會收到執行這些動作所需的授權。

## 步驟 4：檢閱結果及後續步驟
<a name="iot-sns-rule-review-results"></a>

**於本教學課程中：**
+ 您已建立並測試了 Amazon SNS 通知主題和訂閱。
+ 您在規則查詢陳述式中使用了一個簡單的 SQL 查詢和函數，可為您的通知建立一個新訊息。
+ 您已建立 AWS IoT 規則來傳送使用自訂訊息承載的 Amazon SNS 通知。
+ 您使用 MQTT 用戶端來測試 AWS IoT 規則。

**後續步驟**  
使用此規則傳送一些簡訊之後，請嘗試使用其來查看教學課程的某些層面如何影響訊息，及訊息傳送的時間。此處有幾種簡單的入門方式。
+ 變更輸入訊息主題中的 *device\$1id*，並觀察簡訊內容中的影響。
+ 變更規則查詢陳述式中所選取的欄位，並觀察簡訊內容中的影響。
+ 變更規則查詢陳述式中的測試，以測試最低溫度，而非最高溫度。請記得變更 `max_temperature` 的名稱！
+ 新增重新發佈規則動作，以於傳送 SNS 通知時傳送 MQTT 訊息。
+ 請嘗試本系列中的下一個教學課程，並了解如何進行 [教學課程：將裝置資料儲存在 DynamoDB 表格中](iot-ddb-rule.md)。

# 教學課程：將裝置資料儲存在 DynamoDB 表格中
<a name="iot-ddb-rule"></a>

本教學課程示範如何建立將訊息資料傳送至 DynamoDB 資料表的 AWS IoT 規則。

在此教學課程中，您會建立一個規則，將訊息資料從虛構天氣感應器裝置傳送至 DynamoDB 表格。該規則會格式化來自多個天氣感應器的資料，由此可將其新增至單個資料庫表格中。

**您會在本教學課程中學到什麼**
+ 如何建立 DynamoDB 表格
+ 如何從 AWS IoT 規則傳送訊息資料至 DynamoDB 資料表
+ 如何在 AWS IoT 規則中使用替代範本
+ 如何在規則查詢陳述式中使用簡單的 SQL 查詢和函數
+ 如何使用 MQTT 用戶端測試 AWS IoT 規則

此教學課程約需 30 分鐘方能完成。

**Topics**
+ [步驟 1：為本教學課程建立 DynamoDB 表格](#iot-ddb-rule-ddb-table)
+ [步驟 2：建立 AWS IoT 規則以將資料傳送至 DynamoDB 資料表](#iot-ddb-rule-topic-rule)
+ [步驟 3：測試 AWS IoT 規則和 DynamoDB 資料表](#iot-ddb-rule-test)
+ [步驟 4：檢閱結果及後續步驟](#iot-ddb-rule-review)

**開始本教學課程之前，請確定您有：**
+ 

**[設定 AWS 帳戶](setting-up.md)**  
您需要 AWS 帳戶 和 AWS IoT 主控台才能完成本教學課程。
+ 

**檢閱 [使用 MQTT 用戶端檢視 AWS IoT MQTT 訊息](view-mqtt-messages.md)**  
請確定您可使用 MQTT 用戶端來訂閱並發佈至主題。您會使用 MQTT 用戶端，在此程序中測試您的新規則。
+ 

**檢閱了 [Amazon DynamoDB](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/Introduction.html) 概觀**  
若您未曾使用過 DynamoDB，請查閱 [DynamoDB 入門](https://docs.aws.amazon.com//amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html)，以熟悉 DynamoDB 的基本概念和作業。

## 步驟 1：為本教學課程建立 DynamoDB 表格
<a name="iot-ddb-rule-ddb-table"></a>

於本教學課程中，您會建立一個具下列屬性的 DynamoDB 表格，以記錄來自虛構氣候感應器裝置的資料：
+ `sample_time` 為主索引鍵，並說明記錄範例的時間。
+ `device_id` 為排序索引鍵，並說明提供範例的裝置 
+ `device_data` 為從裝置接收並由規則查詢陳述式格式化的資料

**如要建立本教學課程的 DynamoDB 表格**

1. 開啟 [DynamoDB 主控台](https://console.aws.amazon.com//dynamodb/home)，然後選擇 **Create table** (建立表格)。

1. 在 **Create table** (建立資料表) 中：

   1.  於 **Table name** (表格名稱) 中，輸入表格名稱：**wx\$1data**。

   1. 在 **Primary key** (主索引鍵) 中，輸入 **sample\$1time**，然後在欄位旁的選項清單中，選擇 **Number**。

   1. 在 **Sort key** (排序索引鍵) 中，輸入 **device\$1id**，然後在欄位旁的選項清單中，選擇 **Number**。

   1. 請在頁面底部，選擇 **Create** (建立)。

您稍後將在設定 DynamoDB 規則動作時定義 `device_data`。

## 步驟 2：建立 AWS IoT 規則以將資料傳送至 DynamoDB 資料表
<a name="iot-ddb-rule-topic-rule"></a>

於此步驟中，您會使用規則查詢陳述式，格式化虛構天氣感應器裝置的資料，以寫入資料庫表格。

從天氣感應器裝置接收的訊息承載範例如下所示：

```
{
  "temperature": 28,
  "humidity": 80,
  "barometer": 1013,
  "wind": {
    "velocity": 22,
    "bearing": 255
  }
}
```

對於資料庫項目，您會使用規則查詢陳述式將訊息承載的結構平面化，如下所示：

```
{
  "temperature": 28,
  "humidity": 80,
  "barometer": 1013,
  "wind_velocity": 22,
  "wind_bearing": 255
}
```

於此規則中，您還會使用一些 [替代範本](iot-substitution-templates.md)。替代範本是可讓您從函數和訊息資料插入動態值的運算式。

**建立 AWS IoT 規則以將資料傳送至 DynamoDB 資料表**

1. 開啟[AWS IoT 主控台的 Rules (規則) 中樞](https://console.aws.amazon.com//iot/home#/rulehub)。或者，您可以在 AWS 管理主控台 中開啟 AWS IoT 首頁，並導覽至**訊息路由＞規則**。

1. 如要在 **Rules** (規則) 中開始建立新規則，請選擇 **Create rule** (建立規則)。

1. 在 **Rule properties** (規則屬性) 中：

   1. 在 **Rule name** (規則名稱) 中，輸入 **wx\$1data\$1ddb**。

      請記住，規則名稱在您的 AWS 帳戶 和 區域中必須是唯一的，而且不能有任何空格。我們在此名稱中使用底線字元來分隔規則名稱中的兩個單字。

   1. 在 **Rule description** (規則說明) 中，說明規則。

      有意義的說明可讓您更容易記住此規則的作用及您建立規則的原因。說明可依所需而定，因此請盡可能詳細說明。

1. 選擇 **Next** (下一步) 繼續。

1. 在 **SQL statement** (SQL 陳述式) 中：

   1. 在 **SQL version** (SQL 版本) 中，選取 **2016-03-23**。

   1. 在 **SQL statement** (SQL 陳述式) 編輯方塊中，輸入陳述式：

      ```
      SELECT temperature, humidity, barometer,
        wind.velocity as wind_velocity,
        wind.bearing as wind_bearing,
      FROM 'device/+/data'
      ```

      本陳述式：
      + 聆聽具與 `device/+/data` 主題篩選條件相符之主題的 MQTT 訊息。
      + 將 `wind` 屬性的元素格式化為個別屬性。
      + 傳遞 `temperature`、`humidity` 和 `barometer` 屬性不變。

1. 選擇 **Next** (下一步) 繼續。

1. 在 **Rule actions** (規則動作) 中：

   1. 若要開啟此規則的規則動作清單，請於 **Action 1** (動作 1) 中，選擇 **DynamoDB**。
**注意**  
請務必選擇 DynamoDB 而非 DynamoDBv2 作為規則動作。

   1. 於 **Table name** (表格名稱) 中，選擇您在先前步驟中建立的 DynamoDB 表格名稱：**wx\$1data**。

      **Partition key type** (分割區索引鍵類型) 和 **Sort key type** (排序索引鍵類型) 欄位，都會填入 DynamoDB 表格中的值。

   1. 在 **Partition key (分區索引鍵)**，輸入 **sample\$1time**。

   1. 在 **Partition key value (分割區索引鍵值)** 中，輸入 **\$1\$1timestamp()\$1**。

      這是您將用於此規則中 [替代範本](iot-substitution-templates.md) 的首項。而非使用訊息承載中的值，其會使用 timestamp 函數傳回的值。如需進一步了解，請參閱*AWS IoT Core 開發人員指南中*的[時間戳記](iot-sql-functions.md#iot-function-timestamp)。

   1. 在 **Sort key** (排序索引鍵) 中，輸入 **device\$1id**。

   1. 在 **Sort key value (排序索引鍵值)** 中，輸入 **\$1\$1cast(topic(2) AS DECIMAL)\$1**。

      這是您將用於此規則中 [替代範本](iot-substitution-templates.md) 第二項。其會在主題名稱中插入第二個元素值，即裝置的 ID，然後將其轉換為 DECIMAL 值，以與索引鍵的數值格式相符。若要進一步了解主題，請參閱*AWS IoT Core 開發人員指南*中的[主題](iot-sql-functions.md#iot-function-topic)。或者，若要了解將值轉換為數值的詳細資訊，請參閱*AWS IoT Core 開發人員指南*中的[將值轉換為數值](iot-sql-functions.md#iot-sql-function-cast)。

   1. 在 **Write message data to this column (寫入訊息資料至此欄)** 中輸入 **device\$1data**。

      這會建立 DynamoDB 表格中的 `device_data` 欄。

   1. 將 **Operation (操作)** 保持空白。

   1. 在 **IAM Role** (IAM 角色) 中，選擇 **Create a new Role** (建立新角色)。

   1. 在 **Create role** (建立角色) 對話方塊中，請為 **Role name** (角色名稱) 輸入 **wx\$1ddb\$1role**。這個新角色會自動包含以 "aws-iot-rule" 為字首的政策，其允許 **wx\$1data\$1ddb** 規則將資料傳送到您建立的 **wx\$1data** DynamoDB 資料表。

   1. 在 **IAM role** (IAM 角色) 中，選擇 **wx\$1ddb\$1role**。

   1. 請選擇頁面最下方的 **Next** (下一頁)。

1. 請在 **Review and create** (檢閱和建立) 頁面底部，選擇 **Create** (建立) 來建立規則。

## 步驟 3：測試 AWS IoT 規則和 DynamoDB 資料表
<a name="iot-ddb-rule-test"></a>

若要測試新規則，您會使用 MQTT 用戶端來發佈和訂閱用於此測試的 MQTT 訊息。

在新視窗的 [AWS IoT 主控台中開啟 MQTT 用戶端](https://console.aws.amazon.com//iot/home#/test)。這可讓您編輯規則，而不會遺失 MQTT 用戶端的組態。如果您讓它轉到主控台中的另一個頁面，MQTT 用戶端不會保留任何訂閱或訊息記錄。您也需要在主控台中開啟單獨的[AWS IoT 主控台視窗至 DynamoDB Tables 中樞](https://console.aws.amazon.com//dynamodb/home#tables:)，以檢視規則傳送的新項目。

**如要使用 MQTT 用戶端來測試您的規則。**

1. 於 [AWS IoT 主控台的 MQTT 用戶端](https://console.aws.amazon.com//iot/home#/test) 中，訂閱輸入主題 `device/+/data`。

   1. 於 MQTT 用戶端中，選擇 **Subscribe to a topic** (訂閱主題)。

   1. 若為 **Topic filter** (主題篩選條件)，請輸入輸入主題篩選條件的主題 **device/\$1/data**。

   1. 選擇 **Subscribe (訂閱)**。

1. 現在，使用特定裝置 ID **device/22/data** 將訊息發佈至輸入主題。您無法發佈至包含萬用字元的 MQTT 主題。

   1. 於 MQTT 用戶端中，請選擇 **Publish to a topic** (發佈至主題)。

   1. 若為 **Topic name** (主題名稱)，請輸入輸入主題名稱 **device/22/data**。

   1. 若為 **Message payload** (訊息承載)，請輸入下列範例資料。

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. 如要發佈 MQTT 訊息，請選擇 **Publish** (發佈)。

   1. 現在，於 MQTT 用戶端中，選擇 **Subscribe to a topic** (訂閱主題)。於 **Subscribe** (訂閱) 欄中，選擇 **device/\$1/data** 訂閱。確認上一步的範例資料會顯示於此處。

1. 查看您規則所建立 DynamoDB 表格中的列。

   1. 在[AWS IoT 主控台的 DynamoDB Tables 中樞](https://console.aws.amazon.com//dynamodb/home#tables:)中，選擇 **wx\$1data**，然後選擇**項目**索引標籤。

      若您已在 **Items** (項目) 索引標籤上，您可能需要選擇表格標題右上角的重新整理圖示來重新整理該顯示。

   1. 請注意，表格中的 **sample\$1time** 值為連結並開啟一個。若您剛傳送了第一則訊息，則其將是清單中唯一的訊息。

      此連結會顯示表格該列中的所有資料。

   1. 展開 **device\$1data** 項目，查看規則查詢陳述式所產生的資料。

   1. 探索此顯示中可用資料的不同表示法。您亦可於此顯示中編輯資料。

   1. 完成查閱此資料列之後，如要儲存所做的任何變更，請選擇 **Save** (儲存)，或者，如要結束而不儲存任何變更，請選擇 **Cancel** (取消)。

若您並未看到正確的行為，請查看疑難排解提示。

### 對您的 DynamoDB 規則進行疑難排解
<a name="iot-ddb-rule-trouble"></a>

若您並未看到預期的結果，請查看以下事項。
+ 

**您收到錯誤的橫幅**  
若在您發佈輸入訊息時出現錯誤，請先更正該錯誤。下列步驟可協助您修正該錯誤。
+ 

**您並未在 MQTT 用戶端中看到輸入訊息**  
每次您將輸入訊息發佈至 `device/22/data` 主題時，若您依程序中所述訂閱了 `device/+/data` 主題篩選條件，則該訊息應會顯示於 MQTT 用戶端中。

**要檢查的事項**
  + 

**檢查您訂閱的主題篩選條件**  
若您依程序中所述訂閱了輸入訊息主題，則每次發佈輸入訊息時都應該會看到其複本。

    若您並未訊息，請檢查您訂閱的主題名稱，並將其與所發佈的主題進行比較。主題名稱區分大小寫，且您訂閱的主題必須與所發佈訊息承載的主題相同。
  + 

**檢查訊息發佈功能**  
在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下，選擇 **device/\$1/data**，檢查發佈訊息的主題，然後選擇 **Publish to topic** (發佈至主題)。您應該會在訊息清單中出現主題下方的編輯方塊中看到訊息承載。
+ 

**您在 DynamoDB 表格中看不到您的資料**  
首先要做的是選擇表格標題右上角的重新整理圖示，以重新整理顯示。若未顯示您正在尋找的資料，請檢查下列內容。

**要檢查的事項**
  + 

**檢查 MQTT 用戶端 AWS 區域 的 和您建立的規則**  
您正在執行 MQTT 用戶端的主控台必須與您建立的規則處於相同的 AWS 區域。
  + 

**檢查規則查詢陳述式中的輸入訊息主題**  
若要讓規則運作，其必須收到一則訊息，其主題名稱與規則查詢陳述式之 FROM 子句中的主題篩選條件相符。

    檢查規則查詢陳述式中主題篩選條件的拼字與 MQTT 用戶端中主題的拼字。主題名稱區分大小寫，且郵件的主題必須與規則查詢陳述式中的主題篩選條件相符。
  + 

**檢查輸入訊息承載的內容**  
若要讓規則運作，其必須在 SELECT 陳述式中宣告的訊息承載中尋找資料欄位。

    檢查規則查詢陳述式中 `temperature` 欄位的拼字與 MQTT 用戶端中訊息承載的拼字。欄位名稱區分大小寫，規則查詢陳述式中的 `temperature` 欄位必須與訊息承載中的 `temperature` 欄位相符。

    請確定訊息承載中的 JSON 文件格式正確。若 JSON 有任何錯誤，例如缺少逗號，則規則將無法進行讀取。
  + 

**檢查用於規則動作中的索引鍵和欄位名稱**  
用於主題規則中的欄位名稱必須與已發佈訊息之 JSON 訊息承載中找到的欄位名稱相符。

    開啟您建立於主控台中的規則，並檢查規則動作組態中的欄位名稱與用於 MQTT 用戶端中的欄位名稱。
  + 

**檢查規則所使用的角色**  
規則動作必須具有接收原始主題及發佈新主題的權限。

    授權規則以接收訊息資料及更新 DynamoDB 表格的政策是所使用主題特有的。若您變更規則使用的主題或 DynamoDB 表格名稱，則必須更新規則動作的角色，以更新其相符的政策。

    若您懷疑這會是問題，請編輯規則動作並建立新角色。規則動作建立的新角色會收到執行這些動作所需的授權。

## 步驟 4：檢閱結果及後續步驟
<a name="iot-ddb-rule-review"></a>

在您使用此規則將數則訊息傳送至 DynamoDB 表格後，請試著對其進行試驗，以查看變更教學課程中的某些層面如何影響寫入表格的資料。此處有幾種簡單的入門方式。
+ 變更輸入訊息主題中的 *device\$1id*，並觀察對資料的影響。您可使用此來模擬從多個天氣感應器接收資料。
+ 變更規則查詢陳述式中所選取的欄位，並觀察對資料的影響。您可以此來篩選儲存於表格中的資料。
+ 新增重新發佈規則動作，為新增至表格中的每一列傳送 MQTT 訊息。您可以此來進行除錯。

完成本教學課程後，請查看 [教學課程：使用 AWS Lambda 函數格式化通知](iot-lambda-rule.md)。

# 教學課程：使用 AWS Lambda 函數格式化通知
<a name="iot-lambda-rule"></a>

本教學課程示範如何將 MQTT 訊息資料傳送至 AWS Lambda 動作，以格式化和傳送至其他 AWS 服務。在本教學課程中， AWS Lambda 動作會使用 AWS 開發套件，將格式化的訊息傳送至您在教學課程中建立的 Amazon SNS 主題，了解如何 [教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md)。

於有關如何進行 [教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md) 的教學課程中，由規則查詢陳述式產生的 JSON 文件 作為簡訊的主文傳送。結果為一則看似此範例的簡訊：

```
{"device_id":"32","reported_temperature":38,"max_temperature":30}
```

在本教學課程中，您將使用 AWS Lambda 規則動作來呼叫 AWS Lambda 函數，將規則查詢陳述式中的資料格式化為友善格式，例如此範例：

```
Device 32 reports a temperature of 38, which exceeds the limit of 30.
```

您將在本教學課程中建立的 AWS Lambda 函數會使用規則查詢陳述式中的資料來格式化訊息字串，並呼叫 AWS SDK 的 [SNS 發佈](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sns.html#SNS.Client.publish)函數來建立通知。

**您會在本教學課程中學到什麼**
+ 如何建立和測試 AWS Lambda 函數
+ 如何在 AWS Lambda 函數中使用 AWS SDK 發佈 Amazon SNS 通知
+ 如何在規則查詢陳述式中使用簡單的 SQL 查詢和函數
+ 如何使用 MQTT 用戶端測試 AWS IoT 規則

此教學課程約需 45 分鐘方能完成。

**Topics**
+ [步驟 1：建立傳送文字訊息的 AWS Lambda 函數](#iot-lambda-rule-create-lambda)
+ [步驟 2：使用 AWS IoT 規則動作建立 AWS Lambda 規則](#iot-lambda-rule-create-rule)
+ [步驟 3：測試 AWS IoT 規則和 AWS Lambda 規則動作](#iot-lambda-rule-test-rule)
+ [步驟 4：檢閱結果及後續步驟](#iot-lambda-rule-next-steps)

**開始本教學課程之前，請確定您有：**
+ 

**[設定 AWS 帳戶](setting-up.md)**  
您需要 AWS 帳戶 和 AWS IoT 主控台才能完成本教學課程。
+ 

**檢閱 [使用 MQTT 用戶端檢視 AWS IoT MQTT 訊息](view-mqtt-messages.md)**  
請確定您可使用 MQTT 用戶端來訂閱並發佈至主題。您會使用 MQTT 用戶端，在此程序中測試您的新規則。
+ 

**已完成本節中的其他規則教學課程**  
本教學課程需要您於教學課程中建立有關如何進行 [教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md) 的 SNS 通知主題。其亦假設您已完成本節中其他與規則相關的教學課程。
+ 

**檢閱了 [AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html) 概觀**  
如果您 AWS Lambda 未曾使用過 ，請檢閱[AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html)和[開始使用 Lambda](https://docs.aws.amazon.com//lambda/latest/dg/getting-started.html) 以了解其術語和概念。

## 步驟 1：建立傳送文字訊息的 AWS Lambda 函數
<a name="iot-lambda-rule-create-lambda"></a>

本教學課程中的 AWS Lambda 函數會收到規則查詢陳述式的結果、將元素插入文字字串，並將產生的字串作為通知中的訊息傳送至 Amazon SNS。

與[教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md)如何使用規則 AWS IoT 動作傳送通知的 教學課程不同，本教學課程會使用 AWS SDK 的 函數，從 Lambda 函數傳送通知。然而，用於本教學課程中的實際 Amazon SNS 通知主題與您在教學課程中有關如何進行 [教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md) 相同。

**建立傳送文字訊息的 AWS Lambda 函數**

1. 建立新的 AWS Lambda 函數。

   1. 於 [AWS Lambda 主控台](https://console.aws.amazon.com//lambda/home)中，選擇 **Create function** (建立函數)。

   1. 於 **Create function** (建立函數) 中，選取 **Use a blueprint** (使用藍圖)。

      搜尋並選取 **hello-world-python** 藍圖，然後選擇 **Configure** (設定)。

   1. 於**基本資訊**中：

      1. 在 **Function name** (函數名稱) 中，輸入此函數的名稱 **format-high-temp-notification**。

      1. 在**執行角色**中，選擇**從 AWS 政策範本建立新角色**。

      1. 於 Role name (角色名稱) 中，輸入新角色 **format-high-temp-notification-role** 的名稱。

      1. 在 **Policy templates - *optional*** (政策範本：選用) 中，搜尋並選取 **Amazon SNS publish policy** (Amazon SNS 發佈政策)。

      1. 選擇**建立函數**。

1. 修改藍圖程式碼以進行格式化並傳送 Amazon SNS 通知。

   1. 在您建立函數之後，您應該會看到 **format-high-temp-notification** 詳細資訊頁面。若您未看到，請從 [Lambda **函數**](https://console.aws.amazon.com//lambda/home#/functions) 頁面上加以開啟。

   1. 在**format-high-temp-notification** 詳細資訊頁面中，選擇**Configuration** (組態) 索引標籤，然後捲動至 **Function code** (函數程式碼) 面板。

   1. 於 **Function code** (函數程式碼) 視窗的 **Environment** (環境) 窗格中，選擇 Python 檔案 `lambda_function.py`。

   1. 於 **Function code** (函數程式碼) 視窗中，刪除藍圖中的所有原始程式程式碼，並以此程式碼進行取代。

      ```
      import boto3
      #
      #   expects event parameter to contain:
      #   {
      #       "device_id": "32",
      #       "reported_temperature": 38,
      #       "max_temperature": 30,
      #       "notify_topic_arn": "arn:aws:sns:us-east-1:57EXAMPLE833:high_temp_notice"
      #   }
      # 
      #   sends a plain text string to be used in a text message
      #
      #      "Device {0} reports a temperature of {1}, which exceeds the limit of {2}."
      #   
      #   where:
      #       {0} is the device_id value
      #       {1} is the reported_temperature value
      #       {2} is the max_temperature value
      #
      def lambda_handler(event, context):
      
          # Create an SNS client to send notification
          sns = boto3.client('sns')
      
          # Format text message from data
          message_text = "Device {0} reports a temperature of {1}, which exceeds the limit of {2}.".format(
                  str(event['device_id']),
                  str(event['reported_temperature']),
                  str(event['max_temperature'])
              )
      
          # Publish the formatted message
          response = sns.publish(
                  TopicArn = event['notify_topic_arn'],
                  Message = message_text
              )
      
          return response
      ```

   1. 選擇**部署**。

1. 在新視窗中，從教學課程有關如何進行 [教學課程：傳送 Amazon SNS 通知](iot-sns-rule.md) 中查詢您 Amazon SNS 主題的 Amazon 資源名稱 (ARN)。

   1. 於新視窗中，開啟 [Amazon SNS 主控台的主題頁面](https://console.aws.amazon.com//sns/v3/home#/topics)。

   1. 於 **Topics** (主題) 頁面中，於 Amazon SNS 主題清單中尋找 **high\$1temp\$1notice** 通知主題。

   1. 尋找 **high\$1temp\$1notice** 通知主題的 **ARN**，以用於下一個步驟中。

1. 建立您 Lambda 函數的測試案例。

   1. 於主控台的 [Lambda **函數**](https://console.aws.amazon.com//lambda/home#/functions)頁面的 **format-high-temp-notification** 詳細資訊頁面上，選擇該頁面右上角中的 **Select a test event** (選擇測試事件) (即使看似已停用)，然後選擇 **Configure test events** (設定測試事件)。

   1. 於 **Configure test event** (設定測試事件) 中，選擇 **Create new test event** (建立新的測試事件)。

   1. 於 **Event name** (事件名稱) 中，輸入 **SampleRuleOutput**。

   1. 在 **Event name** (事件名稱) 下的 JSON 編輯器，請貼上此範例 JSON 文件。這是您的 AWS IoT 規則將傳送至 Lambda 函數的範例。

      ```
      {
        "device_id": "32",
        "reported_temperature": 38,
        "max_temperature": 30,
        "notify_topic_arn": "arn:aws:sns:us-east-1:57EXAMPLE833:high_temp_notice"
      }
      ```

   1. 請參閱具有 **high\$1temp\$1notice** 通知主題之 **ARN** 的視窗，然後複製 ARN 值。

   1. 以您通知主題的 ARN 取代 JSON 編輯器中的 `notify_topic_arn` 值。

      保持此視窗的開啟狀態，您可於建立 AWS IoT 規則時再次使用此 ARN 值。

   1. 選擇**建立**。

1. 以範例資料測試函數。

   1. 於 **format-high-temp-notification** 詳細資料頁面的右上角中，確認 **SampleRuleOutput** 會顯示於 **Test** (測試) 按鈕旁。若未顯示，請從可用的測試事件清單中進行選擇。

   1. 如要將範例規則輸出訊息傳送至您的函數，請選擇 **Test** (測試)。

若函數和通知皆有效，您會在訂閱通知的手機上收到一則簡訊。

若手機上並未收到簡訊，請檢查作業結果。於 **Function code** (函數程式碼) 面板中的 **Execution result** (執行結果) 索引標籤中，查閱回應以找出發生的任何錯誤。在您的函數可將通知傳送至手機之前，請勿繼續進行下一個步驟。

## 步驟 2：使用 AWS IoT 規則動作建立 AWS Lambda 規則
<a name="iot-lambda-rule-create-rule"></a>

於此步驟中，您會使用規則查詢陳述式，格式化虛構天氣感應器裝置的資料，以傳送至 Lambda 函數，該函數將會格式化並傳送簡訊。

從天氣裝置接收到的訊息承載裝置的範例如下所示：

```
{
  "temperature": 28,
  "humidity": 80,
  "barometer": 1013,
  "wind": {
    "velocity": 22,
    "bearing": 255
  }
}
```

於此規則中，您會使用規則查詢陳述式來建立 Lambda 函數的訊息承載，如下所示：

```
{
  "device_id": "32",
  "reported_temperature": 38,
  "max_temperature": 30,
  "notify_topic_arn": "arn:aws:sns:us-east-1:57EXAMPLE833:high_temp_notice"
}
```

此包含 Lambda 函數格式化及傳送正確簡訊所需的所有資訊。

**建立 AWS IoT 規則以呼叫 Lambda 函數**

1. 開啟 [AWS IoT 主控台的**規則**中樞](https://console.aws.amazon.com//iot/home#/rulehub)。

1. 如要於 **Rules** (規則) 中開始建立新規則，請選擇 **Create** (建立)。

1. 在 **Create a rule** (建立規則) 的頂部中：

   1. 於 **Name** (名稱) 中，輸入規則名稱 **wx\$1friendly\$1text**。

      請記住，規則名稱在您的 AWS 帳戶 和 區域中必須是唯一的，而且不能有任何空格。我們在此名稱中使用底線字元來分隔規則名稱中的兩個單字。

   1.  在 **Description** (說明) 中，說明規則。

      有意義的說明可讓您更容易記住此規則的作用及您建立規則的原因。說明可依所需而定，因此請盡可能詳細說明。

1. 在 **Create a rule** (建立規則) 的 **Rule query statement** (規則查詢陳述式) 中：

   1.  在**使用 SQL 版本**中，選取 **2016-03-23**。

   1. 在 **Rule query statement** (規則查詢陳述式) 編輯方塊中輸入陳述式：

      ```
      SELECT 
        cast(topic(2) AS DECIMAL) as device_id, 
        temperature as reported_temperature,
        30 as max_temperature,
        'arn:aws:sns:us-east-1:57EXAMPLE833:high_temp_notice' as notify_topic_arn
      FROM 'device/+/data' WHERE temperature > 30
      ```

      本陳述式：
      + 聆聽主題與 `device/+/data` 主題篩選條件相符及 `temperature` 值大於 30 的 MQTT 訊息。
      + 從主題字串選取第二個元素，將其轉換為十進位數字，進而指派給 `device_id` 欄位。
      + 從訊息承載選取值 `temperature` 欄位的值，然後將其指派給 `reported_temperature` 欄位。
      + 建立常數值 `30` 來表示限制值，並將其指定給 `max_temperature` 欄位。
      + 建立 `notify_topic_arn` 欄位的常數值。

   1. 請參閱具有 **high\$1temp\$1notice** 通知主題之 **ARN** 的視窗，然後複製 ARN 值。

   1. 以您通知主題的 ARN 取代規則查詢陳述式編輯器中的 ARN 值 (*arn:aws:sns:us-east-1:57EXAMPLE833:high\$1temp\$1notice*)。

1. 於 **Set one or more actions** (設定一個或多個動作) 中：

   1. 若要開啟此規則的規則動作清單，請選擇 **Add action** (新增動作)。

   1. 於 **Select an action** (選取動作) 中，選擇 **Send a message to a Lambda function** (將訊息傳送至 Lambda 函數)。

   1. 若要開啟所選取動作的組態頁面，請在動作清單底部選擇 **Configure action** (設定動作)。

1. 於 **Configure action** (設定動作)：

   1. 於 **Function name** (函數名稱) 中，選擇 **Select** (選取)。

   1. 選擇 **format-high-temp-notification**。

   1. 在 **Configure action** (設定動作) 的底部，選擇 **Add action** (新增動作)。

   1. 如要建立規則，請於 **Create a rule** (建立規則) 中，選擇 **Create rule** (建立規則)。

## 步驟 3：測試 AWS IoT 規則和 AWS Lambda 規則動作
<a name="iot-lambda-rule-test-rule"></a>

若要測試新規則，您將使用 MQTT 用戶端來發佈和訂閱此規則所使用的 MQTT 訊息。

在新視窗的 [AWS IoT 主控台中開啟 MQTT 用戶端](https://console.aws.amazon.com//iot/home#/test)。您現在可以編輯規則，而不會遺失 MQTT 用戶端的設定。如果您讓 MQTT 用戶端前往主控台中的另一個頁面，您將會遺失您的訂閱或訊息記錄。

**如要使用 MQTT 用戶端來測試您的規則。**

1. 在 AWS IoT 主控台的 [MQTT 用戶端](https://console.aws.amazon.com//iot/home#/test) 中，訂閱輸入主題，在此案例中為 `device/+/data`。

   1. 在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下選擇 **Subscribe to a topic** (訂閱主題)。

   1. 在 **Subscription topic** (訂閱主題) 中，輸入輸入主題篩選條件 **device/\$1/data** 的主題 。

   1. 將剩下的欄位保留為其預設設定。

   1. 請選擇 **Subscribe to topic** (訂閱主題)。

      在 **Subscriptions** (訂閱) 欄中，**Publish to a topic** (發佈到主題) 之下，**device/\$1/data** 隨即顯示。

1. 使用特定裝置 ID **device/32/data**，將訊息發佈至輸入主題。您無法發佈至包含萬用字元的 MQTT 主題。

   1. 在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下選擇 **Publish to topic** (發佈至主題)。

   1. 在 **Publish** (發佈) 欄位中輸入輸入主題名稱 **device/32/data**。

   1. 複製此處顯示的範例資料，並在主題名稱下方的編輯方塊中貼上範例資料。

      ```
      {
        "temperature": 38,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. 如要發佈您的 MQTT 訊息，請選擇 **Publish to topic** (發佈至主題)。

1. 確認簡訊已傳送。

   1. 在 MQTT 用戶端中 **Subscriptions** (訂閱) 下，您先前訂閱的主題旁會有一個綠點。

      該綠點表示自上次查看後，已收到一個或多個新訊息。

   1. 於 **Subscriptions** (訂閱) 下，選擇 **device/\$1/data**，來檢查訊息承載是否與您剛剛發佈的內容相符，如下所示：

      ```
      {
        "temperature": 38,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. 檢查您用來訂閱 SNS 主題的手機，並確認訊息承載內容如下所示：

      ```
      Device 32 reports a temperature of 38, which exceeds the limit of 30.
      ```

      若您變更訊息主題中的主題 ID 元素，請記得，僅當訊息主題中的該元素僅包含數字字元時，將 `topic(2)` 值轉換為數值才會有效。

1. 請嘗試傳送溫度不超過限制的 MQTT 訊息。

   1. 在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下選擇 **Publish to topic** (發佈至主題)。

   1. 在 **Publish** (發佈) 欄位中輸入輸入主題名稱 **device/33/data**。

   1. 複製此處顯示的範例資料，並在主題名稱下方的編輯方塊中貼上範例資料。

      ```
      {
        "temperature": 28,
        "humidity": 80,
        "barometer": 1013,
        "wind": {
          "velocity": 22,
          "bearing": 255
        }
      }
      ```

   1. 若要傳送 MQTT 訊息，請選擇 **Publish to topic** (發佈至主題)。

   您應該會看到您在 **device/\$1/data** 訂閱中傳送的訊息；但因溫度值低於規則查詢陳述式中的最高溫度，您不應收到簡訊。

   若您並未看到正確的行為，請查看疑難排解提示。

### 對 AWS Lambda 規則和通知進行故障診斷
<a name="iot-lambda-rule-troubleshoot"></a>

若您並未看到預期的結果，請查看以下事項。
+ 

**您收到錯誤的橫幅**  
若在您發佈輸入訊息時出現錯誤，請先更正該錯誤。下列步驟可協助您修正該錯誤。
+ 

**您並未在 MQTT 用戶端中看到輸入訊息**  
每次您將輸入訊息發佈至 `device/32/data` 主題中，若您依程序中所述訂閱了 `device/+/data` 主題篩選條件，則該訊息應會顯示於 MQTT 用戶端中。

**要檢查的事項**
  + 

**檢查您訂閱的主題篩選條件**  
若您依程序中所述訂閱了輸入訊息主題，則每次發佈輸入訊息時都應該會看到其複本。

    若您並未訊息，請檢查您訂閱的主題名稱，並將其與所發佈的主題進行比較。主題名稱區分大小寫，且您訂閱的主題必須與所發佈訊息承載的主題相同。
  + 

**檢查訊息發佈功能**  
在 MQTT 用戶端中的 **Subscriptions** (訂閱) 下，選擇 **device/\$1/data**，檢查發佈訊息的主題，然後選擇 **Publish to topic** (發佈至主題)。您應該會在訊息清單中出現主題下方的編輯方塊中看到訊息承載。
+ 

**您並未收到 SMS 訊息：**  
若要讓您的規則運作，其必須具有授權其接收訊息和傳送 SNS 通知的正確政策，且必須接收訊息。

**要檢查的事項**
  + 

**檢查 MQTT 用戶端 AWS 區域 的 和您建立的規則**  
您正在執行 MQTT 用戶端的主控台必須與您建立的規則處於相同的 AWS 區域。
  + 

**檢查訊息承載中的溫度值是否超過測試閾值**  
若溫度值小於或等於 30 (如規則查詢陳述式中所定義)，則規則將不會執行其任何動作。
  + 

**檢查規則查詢陳述式中的輸入訊息主題**  
若要讓規則運作，其必須收到一則訊息，其主題名稱與規則查詢陳述式之 FROM 子句中的主題篩選條件相符。

    檢查規則查詢陳述式中主題篩選條件的拼字與 MQTT 用戶端中主題的拼字。主題名稱區分大小寫，且郵件的主題必須與規則查詢陳述式中的主題篩選條件相符。
  + 

**檢查輸入訊息承載的內容**  
若要讓規則運作，其必須在 SELECT 陳述式中宣告的訊息承載中尋找資料欄位。

    檢查規則查詢陳述式中 `temperature` 欄位的拼字與 MQTT 用戶端中訊息承載的拼字。欄位名稱區分大小寫，規則查詢陳述式中的 `temperature` 欄位必須與訊息承載中的 `temperature` 欄位相符。

    請確定訊息承載中的 JSON 文件格式正確。若 JSON 有任何錯誤，例如缺少逗號，則規則將無法進行讀取。
  + 

**檢查 Amazon SNS 通知**  
於 [步驟 1：建立傳送簡訊的 Amazon SNS 主題](iot-sns-rule.md#iot-sns-rule-create-sns-topic) 中，請參閱步驟 3，說明如何測試 Amazon SNS 通知並測試通知以確保通知可正常運作。
  + 

**檢查 Lambda 函數**  
於 [步驟 1：建立傳送文字訊息的 AWS Lambda 函數](#iot-lambda-rule-create-lambda) 中，請參閱步驟 5，說明如何使用測試資料來測試 Lambda 函數，並測試 Lambda 函數。
  + 

**檢查規則所使用的角色**  
規則動作必須具有接收原始主題及發佈新主題的權限。

    授權規則接收訊息資料的政策並加以重新發佈為所使用的主題所特定的。若變更用於重新發佈訊息資料的主題，則必須更新規則動作的角色，來更新其政策以與目前主題相符。

    若您懷疑這會是問題，請編輯 Republish (重新發佈) 規則動作並建立新角色。規則動作建立的新角色會收到執行這些動作所需的授權。

## 步驟 4：檢閱結果及後續步驟
<a name="iot-lambda-rule-next-steps"></a>

**於本教學課程中：**
+ 您已建立 AWS IoT 規則來呼叫 Lambda 函數，該函數會傳送使用自訂訊息承載的 Amazon SNS 通知。
+ 您於規則查詢陳述式中使用了一個簡單的 SQL 查詢和函數，可為您的 Lambda 函數建立一個新訊息承載。
+ 您使用 MQTT 用戶端來測試 AWS IoT 規則。

**後續步驟**  
使用此規則傳送一些簡訊之後，請嘗試使用其來查看教學課程的某些層面如何影響訊息，及訊息傳送的時間。此處有幾種簡單的入門方式。
+ 變更輸入訊息主題中的 *device\$1id*，並觀察簡訊內容中的影響。
+ 變更規則查詢陳述式中所選取的欄位、更新 Lambda 函數以於新訊息中加以使用，並觀察簡訊內容中的影響。
+ 變更規則查詢陳述式中的測試，以測試最低溫度，而非最高溫度。更新 Lambda 函數以格式化新的訊息，並記得變更 `max_temperature` 的名稱。
+ 若要進一步了解如何尋找在您開發和使用 AWS IoT 規則時可能發生的錯誤，請參閱 [監控 AWS IoT](monitoring_overview.md)。

# 在裝置離線時保留裝置狀態
<a name="iot-shadows-tutorial"></a>

這些教學課程說明如何使用 AWS IoT Device Shadow 服務來存放和更新裝置的狀態資訊。Shadow 文件是一個 JSON 文件，其根據裝置、本機應用程式或服務發佈的訊息，顯示裝置狀態的變化。於本教學課程中，Shadow 文件會顯示燈泡顏色的變化。這些教學課程還會顯示影子如何在裝置與網際網路中斷連線時，儲存此資訊，並在裝置回復連線並請求此資訊時，將最新狀態資訊傳回裝置。

建議您依此處顯示的順序試試這些教學課程，從您需要建立的 AWS IoT 資源和必要的硬體設定開始，這亦可協助您逐步學習概念。這些教學課程示範如何設定和連接 Raspberry Pi 裝置以搭配 使用 AWS IoT。若您並無所需的硬體，您可依照這些教學課程進行調整，以適應您選擇的裝置或[使用 Amazon EC2 建立虛擬裝置](creating-a-virtual-thing.md)。

**教學課程案例概觀**  
這些教學課程的案例為本機應用程式或服務，可變更燈泡的顏色，及將其資料發佈置預留的影子主題。這些教學課程類似於[互動式入門教學課程](interactive-demo.md)中說明的 Device Shadow 功能，並在 Raspberry Pi 裝置實作。本節中的教學課程側重於單一經典影子裝置，同時展現如何容納已命名影子或多個裝置的方法。

下列教學課程將協助您了解如何使用 AWS IoT Device Shadow 服務。
+ 

**[教學課程：準備好 Raspberry Pi 來執行影子應用程式](create-resources-shadow.md)**  
本教學課程說明如何設定 Raspberry Pi 裝置以進行連線 AWS IoT。您也將建立 AWS IoT 政策文件和物件資源、下載憑證，然後將政策連接到該物件資源。此教學課程約需 30 分鐘方能完成。
+ 

**[教學課程：安裝裝置 SDK 並執行 Device Shadows 的範例應用程式](lightbulb-shadow-application.md)**  
本教學課程說明如何安裝必要的工具、軟體和適用於 Python 的 AWS IoT 裝置 SDK，然後執行範例陰影應用程式。本教學課程以 [連接 Raspberry Pi 或其他裝置](connecting-to-existing-device.md) 中提出的概念為基礎，需 20 分鐘才能完成。
+ 

**[教學課程：使用範例應用程式和 MQTT 測試用戶端，與 Device Shadow 互動](interact-lights-device-shadows.md)**  
本教學課程示範如何使用`shadow.py`範例應用程式和**AWS IoT 主控台**來觀察 AWS IoT Device Shadows 與燈泡狀態變更之間的互動。本教學課程也會展示如何將 MQTT 訊息傳送至 Device Shadow 的預留主題。此教學課程約需 45 分鐘方能完成。

**AWS IoT Device Shadow 概觀**  
Device Shadow 是由您在 AWS IoT 登錄檔中建立的[物件資源](iot-thing-management.md)管理之裝置的持久性虛擬表示法。Shadow 文件是個 JSON 或 JavaScript 標記法文件，用來存儲和檢索裝置的目前狀態資訊。您可透過 MQTT 或 HTTP REST API，使用影子來取得及設定裝置的狀態 (無論該裝置是否連線至網際網路)。

Shadow 的文件包含 `state` 屬性，說明裝置狀態的下列層面：
+ `desired`：應用程式會透過更新 `desired` 物件來指定裝置屬性的所需狀態。
+ `reported`：裝置會報告其在 `reported` 物件中的目前狀態。
+ `delta`： AWS IoT 報告 `delta` 物件中所需狀態與報告狀態之間的差異。

以下為 Shadow 狀態文件的範例：

```
{
  "state": {
    "desired": {
      "color": "green"
      },
    "reported": {
      "color": "blue"
      },
    "delta": {
      "color": "green"
      }
   }
}
```

如要更新裝置的 Shadow 文件，您可使用[預留的 MQTT 主題](reserved-topics.md#reserved-topics-shadow)、以 HTTP 支援 `GET`、`UPDATE` 和 `DELETE` 操作的 [Device Shadow REST API](device-shadow-rest-api.md)，以及 [AWS IoT CLI](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iot-data/index.html)。

在上一個範例中，假設您想將 `desired` 顏色變更為 `yellow`。如要執行此動作，請傳送請求至 [UpdateThingShadow](device-shadow-rest-api.md#API_UpdateThingShadow) API 或將訊息發佈至[更新](device-shadow-mqtt.md#update-pub-sub-topic)主題 `$aws/things/THING_NAME/shadow/update`。

```
{
  "state": {
    "desired": {
      "color": yellow
    }
  }
}
```

更新只會影響請求中所指定的欄位。成功更新 Device Shadow 後， 會將新`desired`狀態 AWS IoT 發佈至`delta`主題 `$aws/things/THING_NAME/shadow/delta`。於此狀況下，Shadow 文件看起來像這樣：

```
{
  "state": {
    "desired": {
      "color": yellow
    },
    "reported": {
      "color": green
    },
    "delta": {
      "color": yellow
      }
  }
}
```

接著會使用`$aws/things/THING_NAME/shadow/update`具有下列 JSON 訊息`Update`的主題，向 AWS IoT Device Shadow 報告新狀態：

```
{
  "state": {
    "reported": {
      "color": yellow
    }
  }
}
```

若您想要取得目前的狀態資訊，請將請求傳送至 [GetThingShadow](device-shadow-rest-api.md#API_GetThingShadow) API 或將 MQTT 訊息發佈至[取得](device-shadow-mqtt.md#get-pub-sub-topic)主題 `$aws/things/THING_NAME/shadow/get`。

如需使用 Device Shadow 服務的相關資訊，請參閱 [AWS IoT Device Shadow 服務](iot-device-shadows.md)。

如需在裝置、應用程式和服務中使用 Device Shadows 的詳細資訊，請參閱 [在裝置中使用影子](device-shadow-comms-device.md) 和 [在應用程式和服務中使用影子](device-shadow-comms-app.md)。

如需與 AWS IoT 陰影互動的資訊，請參閱 [與影子互動](device-shadow-data-flow.md)。

如需 MQTT 預留主題和 HTTP REST API 的相關資訊，請參閱 [Device Shadow MQTT 主題](device-shadow-mqtt.md) 和 [Device Shadow REST API](device-shadow-rest-api.md)。

# 教學課程：準備好 Raspberry Pi 來執行影子應用程式
<a name="create-resources-shadow"></a>

本教學課程示範如何設定 Raspberry Pi 裝置，以及建立裝置連線和交換 MQTT 訊息所需的 AWS IoT 資源。

**注意**  
若您打算 [使用 Amazon EC2 建立虛擬裝置](creating-a-virtual-thing.md)，則可跳過本頁，並繼續 [設定您的裝置](configure-device.md)。當您建立虛擬物件時，您將會建立這些資源。若您想使用不同的裝置，而非 Raspberry Pi，您可嘗試依照這些教學課程進行調整，使其適應您選擇的裝置。

**於本教學課程中，您會了解如何：**
+ 設定 Raspberry Pi 裝置並將其設定為搭配 使用 AWS IoT。
+ 建立 AWS IoT 政策文件，授權您的裝置與服務 AWS IoT 互動。
+  AWS IoT 在 X.509 裝置憑證中建立物件資源，然後連接政策文件。

  問題是您的裝置在 AWS IoT 登錄檔中的虛擬表示。憑證會將您的裝置驗證為 AWS IoT Core，而政策文件會授權您的裝置與之互動 AWS IoT。

**如何執行本教學課程**  
如要執行 Device Shadows 的 `shadow.py` 範例應用程式，您需要一個連接至 AWS IoT的 Raspberry Pi 裝置。我們建議您依照此處顯示的順序學習本教學課程，從設定 Raspberry Pi 及其配件開始，然後建立政策，並將政策連接至您建立的物件資源。然後，您可以使用 Raspberry Pi 支援的圖形使用者介面 (GUI) 來遵循本教學課程，在裝置的 Web 瀏覽器上開啟 AWS IoT 主控台，這也可以讓您更輕鬆地直接將憑證下載到 Raspberry Pi 以進行連線 AWS IoT。

**開始本教學課程之前，請確定您有：**
+  AWS 帳戶。若您沒有帳戶，請完成 [設定 AWS 帳戶](setting-up.md) 所述的步驟，然後再繼續。您需要 AWS 帳戶 和 AWS IoT 主控台才能完成本教學課程。
+ Raspberry Pi 及其必要的配件。您會需要：
  + [Raspberry Pi 3 代 B 型](https://www.raspberrypi.com/products/)或更新的型號。本教學課程可能適用於較早版本的 Raspberry Pi，但我們尚未對其進行測試。
  + [Raspberry Pi OS (32 位元)](https://www.raspberrypi.com/software/operating-systems/) 或更新版本。我們建議您使用最新版本的 Raspberry Pi 作業系統。較早版本的作業系統可能適用，但我們尚未對其進行測試。
  + 乙太網路或 Wi-Fi 連線。
  + 鍵盤、滑鼠、顯示器、纜線和電源供應器。

此教學課程約需 30 分鐘方能完成。

## 步驟 1：設定及配置 Raspberry Pi 裝置
<a name="setup-device-shadow"></a>

在本節中，我們將設定 Raspberry Pi 裝置以搭配 使用 AWS IoT。

**重要**  
調整這些指示以適用其他裝置和作業系統可能是一項艱鉅的挑戰。您必須充分了解您的裝置，才能解譯這些指示並將其套用至您的裝置。若遇到困難，您可嘗試使用其他裝置選項的一項作為替代選項，例如 [使用 Amazon EC2 建立虛擬裝置](creating-a-virtual-thing.md) 或 [使用您的 Windows 或 Linux PC 或 Mac 做為 AWS IoT 裝置](using-laptop-as-device.md)。

您需要配置 Raspberry Pi，使其可以啟動作業系統 (OS)，連接至網際網路，並可讓您在命令列介面與其互動。您也可以使用 Raspberry Pi 支援的圖形使用者介面 (GUI) 來開啟 AWS IoT 主控台並執行本教學課程的其餘部分。

**設定 Raspberry Pi**

1. 將 SD 卡插入 Raspberry Pi 上的 MicroSD 記憶卡插槽。有些 SD 卡會預先載入安裝管理員，在啟動主機板後提示您安裝作業系統的選單。您也可使用 Raspberry Pi 成像器，在卡上安裝作業系統。

1. 將 HDMI 電視或顯示器連接至連接到 Raspberry Pi 之 HDMI 連接埠的 HDMI 纜線。

1. 將鍵盤和滑鼠連接至 Raspberry Pi 的 USB 連接埠，然後插入電源整流器以啟動機板。

Raspberry Pi 啟動後，若 SD 卡預先載入安裝管理員，會出現一個安裝作業系統的選單。若於安裝作業系統時發生問題，您可試試下列步驟。如需有關 Raspberry Pi 的設定資訊，請參閱[設定 Raspberry Pi](https://projects.raspberrypi.org/en/projects/raspberry-pi-setting-up/)。

**若您在設定 Raspberry Pi 時發生問題：**
+ 在啟動機板之前，請檢查是否已插入 SD 卡。若您在啟動機板後插入 SD 卡，則安裝選單可能不會顯示。
+ 確認電視或顯示器已開啟，且已選取正確的輸入。
+ 確保您正在使用 Raspberry Pi 相容的軟體。

安裝並設定 Raspberry Pi 作業系統之後，請開啟 Raspberry Pi 的 Web 瀏覽器，然後導覽至 AWS IoT Core 主控台以繼續本教學課程中的其餘步驟。

如果您可以開啟 AWS IoT Core 主控台，表示 Raspberry Pi 已準備就緒，您可以繼續 [教學課程：在 中佈建您的裝置 AWS IoT](shadow-provision-cloud.md)。

若您仍然無法解決問題或需要其他協助，請參閱[獲取有關 Raspberry Pi 的協助](https://projects.raspberrypi.org/en/projects/raspberry-pi-setting-up/5)。

# 教學課程：在 中佈建您的裝置 AWS IoT
<a name="shadow-provision-cloud"></a>

本節會建立教學課程將使用 AWS IoT Core 的資源。

**Topics**
+ [步驟 1：建立 Device Shadow AWS IoT 的政策](#create-policy-shadow)
+ [步驟 2：建立物件資源並將政策連接至該物件](#create-thing-shadow)
+ [步驟 3：檢閱結果及後續步驟](#resources-shadow-review)

## 步驟 1：建立 Device Shadow AWS IoT 的政策
<a name="create-policy-shadow"></a>

X.509 憑證透過 AWS IoT Core. AWS IoT policies 驗證您的裝置，會連接到允許裝置執行 AWS IoT 操作的憑證，例如訂閱或發佈至 Device Shadow 服務所使用的 MQTT 預留主題。您的裝置會在連線並傳送訊息時提供其憑證 AWS IoT Core。

在此過程中，您將會建立一個政策，可讓您的裝置執行 AWS IoT 執行範例程式所需的作業。建議您建立政策，該政策僅授予執行任務所需的許可權。首先建立 AWS IoT 政策，然後將其連接到稍後建立的裝置憑證。

**建立 AWS IoT 政策**

1. 請在左側選單上選擇 **Secure** (安全)，然後選擇 **Policies** (政策)。若您的帳戶具有現有政策，請選擇 **Create** (建立)，否則，在 **You don’t have a policy yet** (您尚未設定政策) 頁面上，選擇 **Create a policy** (建立政策)。

1. 在 **Create policy** (建立政策) 頁面上：

   1. 在 **Name** (名稱) 欄位中，輸入政策的名稱 (例如，**My\$1Device\$1Shadow\$1policy**)。請勿在政策名稱中使用個人識別資訊。

   1. 在政策文件中，您說明了連線、訂閱、接收和發佈動作，這些動作授予裝置發佈和訂閱 MQTT 預留主題的許可權限。

      複製下列範例政策，並將其貼入您的政策文件中：`thingname` 將 取代為您建立的物件名稱 （例如 `My_light_bulb`)、`region`將 取代為您使用 服務的 AWS IoT 區域，並將 `account`取代為您的 AWS 帳戶 號碼。如需 AWS IoT 政策的詳細資訊，請參閱 [AWS IoT Core 政策](iot-policies.md)。  
****  

      ```
      {
          "Version":"2012-10-17",		 	 	 
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Publish"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingname/shadow/get",
                      "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingname/shadow/update"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Receive"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingname/shadow/get/accepted",
                      "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingname/shadow/get/rejected",
                      "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingname/shadow/update/accepted",
                      "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingname/shadow/update/rejected",
                      "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/thingname/shadow/update/delta"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": [
                      "iot:Subscribe"
                  ],
                  "Resource": [
                      "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingname/shadow/get/accepted",
                      "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingname/shadow/get/rejected",
                      "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingname/shadow/update/accepted",
                      "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingname/shadow/update/rejected",
                      "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/thingname/shadow/update/delta"
                  ]
              },
              {
                  "Effect": "Allow",
                  "Action": "iot:Connect",
                  "Resource": "arn:aws:iot:us-east-1:123456789012:client/test-*"
              }
          ]
      }
      ```

## 步驟 2：建立物件資源並將政策連接至該物件
<a name="create-thing-shadow"></a>

連線至 的裝置 AWS IoT 可由 AWS IoT 登錄檔中的*物件資源*表示。*物件資源*意指特定裝置或邏輯實體，例如本教學課程中的燈泡。

若要了解如何在 中建立物件 AWS IoT，請遵循中所述的步驟[建立物件](create-iot-resources.md#create-aws-thing)。當您依照該教學課程中的步驟時，請注意以下一些關鍵事項：

1. 選擇 **Create a single thing** (建立單一物件)，在 **Name** (名稱) 欄位中，輸入與您先前建立政策時指定之 `thingname` 相同的物件名稱 (例如，`My_light_bulb`)。

   物件類型建立之後，您就無法變更其名稱。若您給它一個不同於 `thingname` 的名字，請建立名為 `thingname` 的新物件並刪除舊物件。
**注意**  
請勿在物件名稱中使用個人識別資訊。物件名稱可以出現在未加密的通訊和報告中。

1. 我們建議您將**憑證已建立！**頁面上的每個憑證檔案下載至您可輕鬆找到的位置。您必須安裝這些檔案，才能執行範例應用程式。

   建議您將檔案下載至 Raspberry Pi `home` 目錄中的 `certs` 子目錄上，並使用如下表中所建議更簡單名稱對其進行命名。  
**憑證檔案名稱**    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/shadow-provision-cloud.html)

1. 啟用憑證以啟用連線後 AWS IoT，請選擇**連接政策**，並確保您將先前建立的政策 （例如，**My\$1Device\$1Shadow\$1policy**) 連接到物件。

   建立物件之後，您可以在 AWS IoT 主控台的物件清單中看到您的物件資源。

## 步驟 3：檢閱結果及後續步驟
<a name="resources-shadow-review"></a>

**在本教學課程中，您會了解如何：**
+ 設定及配置 Raspberry Pi 裝置。
+ 建立 AWS IoT 政策文件，授權您的裝置與 AWS IoT 服務互動。
+ 建立物件資源和相關聯的 X.509 裝置憑證，並將政策文件與其進行連接。

**後續步驟**  
您現在可以安裝適用於 Python AWS IoT 的裝置 SDK、執行`shadow.py`範例應用程式，並使用 Device Shadows 控制狀態。如需如何執行本教學課程的詳細資訊，請參閱 [教學課程：安裝裝置 SDK 並執行 Device Shadows 的範例應用程式](lightbulb-shadow-application.md)。

# 教學課程：安裝裝置 SDK 並執行 Device Shadows 的範例應用程式
<a name="lightbulb-shadow-application"></a>

本節說明如何安裝必要的軟體和適用於 Python 的 AWS IoT Device SDK，並執行`shadow.py`範例應用程式來編輯 Shadow 文件並控制影子的狀態。

**於本教學課程中，您會了解如何：**
+ 使用已安裝的軟體和適用於 Python 的 AWS IoT Device SDK 來執行範例應用程式。
+ 了解如何使用範例應用程式輸入值，以於 AWS IoT 主控台中發佈所需的值。
+ 檢閱 `shadow.py` 範例應用程式，及其如何使用 MQTT 通訊協定來更新影子的狀態。

**在您執行此教學課程之前：**  
您必須設定好 AWS 帳戶、設定 Raspberry Pi 裝置，並建立 AWS IoT 物件和政策，授予裝置發佈和訂閱 Device Shadow 服務 MQTT 預留主題的許可。如需詳細資訊，請參閱[教學課程：準備好 Raspberry Pi 來執行影子應用程式](create-resources-shadow.md)。

您還必須安裝 Git、Python 和適用於 Python 的 AWS IoT 裝置 SDK。本教學課程是以教學課程 [連接 Raspberry Pi 或其他裝置](connecting-to-existing-device.md) 中提出的概念為基礎。若您尚未嘗試該教學課程，建議您依照該教學課程中說明的步驟，安裝憑證檔案和裝置 SDK，然後回到本教學課程，執行 `shadow.py` 範例應用程式。

**Topics**
+ [步驟 1：執行 shadow.py 範例應用程式](#run-sample-application-shadows)
+ [步驟 2：檢閱 shadow.py 裝置 SDK 範例應用程式](#review-shadow-sample-code)
+ [步驟 3：使用 `shadow.py` 範例應用程式進行疑難排解](#shadow-sample-app-troubleshoot)
+ [步驟 4：檢閱結果及後續步驟](#sample-app-shadow-review)

此教學課程約需 20 分鐘方能完成。

## 步驟 1：執行 shadow.py 範例應用程式
<a name="run-sample-application-shadows"></a>

執行 `shadow.py` 範例應用程式之前，除了您所安裝之憑證檔案的名稱和位置之外，您還需要下列資訊。


**應用程式參數值**  

|  參數  |  可在哪裡找到值  | 
| --- | --- | 
| your-iot-thing-name |  您先前在 中建立的 AWS IoT 物件名稱[步驟 2：建立物件資源並將政策連接至該物件](shadow-provision-cloud.md#create-thing-shadow)。 如要尋找此值，請於 [AWS IoT 主控台](https://console.aws.amazon.com/iot/home)中，依序選擇 **Manage** (管理) 和 **Things** (物件)。  | 
| your-iot-endpoint |   *your-iot-endpoint* 值的格式為：`endpoint_id-ats.iot.region.amazonaws.com`，例如 `a3qj468EXAMPLE-ats.iot.us-west-2.amazonaws.com`。如要尋找此值： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/lightbulb-shadow-application.html)  | 

**安裝並執行範例應用程式**

1. 導覽至範例應用程式目錄。

   ```
   cd ~/aws-iot-device-sdk-python-v2/samples/service-clients
   ```

1. 在命令列視窗中，按照指示替換 *your-iot-endpoint* 和 *your-iot-thing-name* 並執行此命令。

   ```
   python3 shadow.py --ca_file ~/certs/Amazon-root-CA-1.pem --cert ~/certs/device.pem.crt --key ~/certs/private.pem.key --endpoint your-iot-endpoint --thing_name your-iot-thing-name
   ```

1. 觀察範例應用程式：

   1. 連線至您帳戶的 AWS IoT 服務。

   1. 訂閱 `Delta` 事件和 `Update` 與 `Get` 回應。

   1. 提示您在終端機終輸入所需的值。

   1. 顯示類似下列內容的輸出：

   ```
   Connecting to a3qEXAMPLEffp-ats.iot.us-west-2.amazonaws.com with client ID 'test-0c8ae2ff-cc87-49d2-a82a-ae7ba1d0ca5a'...
   Connected!
   Subscribing to Delta events...
   Subscribing to Update responses...
   Subscribing to Get responses...
   Requesting current shadow state...
   Launching thread to read user input...
   Finished getting initial shadow state.
   Shadow contains reported value 'off'.
   Enter desired value:
   ```

**注意**  
若在執行 `shadow.py` 範例應用程式時發生問題，請檢閱 [步驟 3：使用 `shadow.py` 範例應用程式進行疑難排解](#shadow-sample-app-troubleshoot)。如要取得可協助您修正問題的其他資訊，請將 `--verbosity debug` 參數新增至命令列，以便範例應用程式會顯示有關其正在執行之動作的詳細訊息。

**輸入值並觀察 Shadow 文件中的更新**  
您可於終端機中輸入值，以指定 `desired` 值，其還會更新 `reported` 值。假設您在終端機中輸入顏色 `yellow`。`reported` 值也會更新為顏色 `yellow`。下列展示顯示於終端機中的訊息：

```
Enter desired value:
yellow
Changed local shadow value to 'yellow'.
Updating reported shadow value to 'yellow'...
Update request published.
Finished updating reported shadow value to 'yellow'.
```

當您發佈此更新請求時， 會為物件資源 AWS IoT 建立預設、傳統陰影。您可以查看您建立之物件資源的 Shadow 文件 （例如，)，以觀察您發佈至 AWS IoT 主控台中 `reported`和 `desired`值的更新請求`My_light_bulb`。如要在 Shadow 文件中查看更新：

1. 在 AWS IoT 主控台中，選擇**管理**，然後選擇**實物**。

1. 在顯示的物件清單中，選取您所建立的物件，然後依序選擇 **Shadows** (影子) 和 **Classic Shadow** (經典影子)。

Shadow 文件應看似如下列內容，顯示設定為顏色 `yellow` 的 `reported` 和 `desired` 值。您會在文件的 **Shadow state** (影子狀態) 區段中看到這些值。

```
{
"desired": {
  "welcome": "aws-iot",
  "color": "yellow"
},
"reported": {
  "welcome": "aws-iot",
  "color": "yellow"
}
}
```

您還會看到 **Metadata** (中繼資料) 區段，其包含請求之時間戳記資訊和版本號碼。

您可以使用狀態文件版本，確認您正在更新的裝置影子文件為最新版本。若您傳送另一個更新請求，版本編號會遞增 1。當您為更新請求提供版本，若狀態文件的目前版本與提供的版本不符，則服務會拒絕請求並顯示 HTTP 409 衝突回應代碼。

```
{
"metadata": {
  "desired": {
    "welcome": {
      "timestamp": 1620156892
    },
    "color": {
      "timestamp": 1620156893
    }
  },
  "reported": {
    "welcome": {
      "timestamp": 1620156892
    },
    "color": {
      "timestamp": 1620156893
    }
  }
},
"version": 10
}
```

如要了解 Shadow 文件的更多資訊並觀察狀態資訊的變更，請繼續參閱說明於本教學課程 [步驟 4：檢閱結果及後續步驟](#sample-app-shadow-review) 部分中的下一個教學課程 [教學課程：使用範例應用程式和 MQTT 測試用戶端，與 Device Shadow 互動](interact-lights-device-shadows.md)。或者，您還可於下一節中了解 `shadow.py` 範本程式碼及其如何使用 MQTT 通訊協定。

## 步驟 2：檢閱 shadow.py 裝置 SDK 範例應用程式
<a name="review-shadow-sample-code"></a>

本節會從用於本教學課程中之**適用於 Python 的AWS IoT 裝置 SDK v2** 檢閱 `shadow.py` 範例應用程式。在這裡，我們將 AWS IoT Core 使用 MQTT 和透過 WSS 通訊協定的 MQTT 來檢閱它如何連接到 。[AWS 通用執行時間 (AWS-CRT)](https://github.com/awslabs/aws-crt-python#aws-crt-python) 程式庫提供低階通訊協定支援，並包含在適用於 Python 的 AWS IoT Device SDK v2 中。

雖然本教學課程透過 WSS 使用 MQTT 和 MQTT， AWS IoT 支援發佈 HTTPS 請求的裝置。有關從裝置傳送 HTTP 訊息的 Python 程式範例，請參閱使用 Python `requests` 程式庫的 [HTTPS 程式碼範例](http.md#codeexample)。

如需有關如何決定裝置通訊所使用之通訊協定的詳細資訊，請參閱 [選擇裝置通訊的應用程式通訊協定](protocols.md#protocol-selection)。

**MQTT**  
`shadow.py` 範例呼叫 [https://github.com/awslabs/aws-crt-python/blob/89207bcf1387177034e02fe29e8e469ca45e39b7/awscrt/awsiot_mqtt_connection_builder.py](https://github.com/awslabs/aws-crt-python/blob/89207bcf1387177034e02fe29e8e469ca45e39b7/awscrt/awsiot_mqtt_connection_builder.py) 中的 `mtls_from_path` (如圖所示)，使用 MQTT 通訊協定來建立與 AWS IoT Core 的連線。`mtls_from_path` 會使用 X.509 憑證和 TLS v1.2 來驗證裝置。 AWS CRT 程式庫會處理該連線的較低層級詳細資訊。

```
mqtt_connection = mqtt_connection_builder.mtls_from_path(
  endpoint=args.endpoint,
  cert_filepath=args.cert,
  pri_key_filepath=args.key,
  ca_filepath=args.ca_file,
  client_bootstrap=client_bootstrap,
  on_connection_interrupted=on_connection_interrupted,
  on_connection_resumed=on_connection_resumed,
  client_id=args.client_id,
  clean_session=False,
  keep_alive_secs=6
)
```
+ `endpoint` 是您從命令列傳入的 AWS IoT 端點，`client_id`也是 中唯一識別此裝置的 ID AWS 區域。
+ `cert_filepath`、`pri_key_filepath` 和 `ca_filepath` 是裝置憑證和私密金鑰檔案及根 CA 檔案的路徑。
+ `client_bootstrap` 是處理通訊端通訊活動的通用執行時間物件，並在呼叫 `mqtt_connection_builder.mtls_from_path` 之前實例化。
+ `on_connection_interrupted` 和 `on_connection_resumed` 是在裝置連線遭到中斷並回復時呼叫的回呼函數。
+ `clean_session` 為是否啟動一個新的、持續的工作階段，或若存在，則進行重新連線。`keep_alive_secs` 為 `CONNECT` 請求中傳送的保持活動值，以秒為單位。Ping 會在此時間間隔自動傳送。若在此值的 1.5 倍之後未收到 ping，則伺服器會假設連線中斷。

`shadow.py` 範例還會呼叫 [https://github.com/awslabs/aws-crt-python/blob/89207bcf1387177034e02fe29e8e469ca45e39b7/awscrt/awsiot_mqtt_connection_builder.py](https://github.com/awslabs/aws-crt-python/blob/89207bcf1387177034e02fe29e8e469ca45e39b7/awscrt/awsiot_mqtt_connection_builder.py) 中的 `websockets_with_default_aws_signing`，使用透過 WSS 的 MQTT 通訊協定建立與 AWS IoT Core 的連線。透過 WSS 的 MQTT 還會使用與 MQTT 相同的參數，並採用下列其他參數：
+ `region` 是 Signature V4 身分驗證所使用的 AWS 簽署區域，`credentials_provider`也是提供用於身分驗證的 AWS 登入資料。從命令列傳入 Region (區域)，並在呼叫 `mqtt_connection_builder.websockets_with_default_aws_signing` 之前將 `credentials_provider` 物件實例化。
+ 若使用代理主機，`websocket_proxy_options` 是 HTTP 代理選項。在 `shadow.py` 範例應用程式中，此值在呼叫 `mqtt_connection_builder.websockets_with_default_aws_signing` 之前進行實例化。

**訂閱 Shadow 主題和事件**  
`shadow.py` 範例嘗試建立連線，並等待完整連線。若未連線，則指令會排入佇列中。連線後，範例會訂閱差異事件及更新和取得訊息，並發佈服務品質 (QoS) 層級為 1 (`mqtt.QoS.AT_LEAST_ONCE`) 的訊息。

當裝置訂閱 QoS 層級 1 的訊息時，訊息代理程式會儲存裝置訂閱的訊息，直至其可傳送至裝置為止。訊息代理程式會重新傳送訊息，直至收到來自裝置的 `PUBACK` 回應。

如需 MQTT 通訊協定的詳細資訊，請參閱 [檢閱 MQTT 通訊協定](sdk-tutorials.md#sdk-tutorials-mqtt-review) 和 [MQTT](mqtt.md)。

如需用於本教學課程中的 MQTT、透過 WSS 的 MQTT、持續性工作階段及 QoS 層級的詳細資訊，請參閱 [檢閱 pubsub.py 裝置 SDK 範例應用程式](sdk-tutorials.md#sdk-tutorials-explore-sample)。

## 步驟 3：使用 `shadow.py` 範例應用程式進行疑難排解
<a name="shadow-sample-app-troubleshoot"></a>

當您執行 `shadow.py` 範例應用程式時，您應會看到一些顯示於終端機中的訊息，並提示輸入 `desired` 值。若程式拋出錯誤，則如要偵錯，您可先檢查是否為您的系統執行正確的命令。

在某些狀況下，錯誤訊息可能表示連線問題，且看似如下：`Host name was invalid for dns resolution` 或 `Connection was closed unexpectedly`。於此狀況下，您可檢查下列事項：
+ 

**檢查命令中的端點的地址**  
請檢閱您為執行範例應用程式 (例如 `a3qEXAMPLEffp-ats.iot.us-west-2.amazonaws.com`) 輸入命令中的 `endpoint` 引數，並在 **AWS IoT 主控台** 中檢查此值。

  如要檢查您是否使用了正確的值：

  1. 於 **AWS IoT 主控台**中，依序選擇 **Manage** (管理) 和 **Things** (物件)。

  1. 選擇您為範例應用程式建立的物件 (例如，**My\$1light\$1bulb**)，然後選擇 **Interact** (互動)。

  在物件詳細資料頁面上，您的端點會顯示於 **HTTPS** 區段中。您應該也會看到訊息：`This thing already appears to be connected.`
+ 

**檢查憑證啟用**  
憑證會使用 驗證您的裝置 AWS IoT Core。

  如要檢查您的憑證是否為作用中：

  1. 於 **AWS IoT 主控台**中，依序選擇 **Manage (管理)** 和 **Things (物件)**。

  1. 選擇您為範例應用程式建立的物件 (例如，**My\$1light\$1bulb**)，然後選擇 **Security** (安全性)。

  1. 選取憑證，然後從憑證的詳細資料頁面選擇 Select the certificate (選取憑證)，然後從憑證的詳細資料頁面選擇 **Actions** (動作)。

  若於下拉式清單中 **Activate** (啟用) 無法使用，則您只能選擇 **Deactivate**(停用)，表示您的憑證處於作用中。若無，請選擇 **Activate** (啟用)，然後重新執行範例程式。

  若程式仍然無法執行，請檢查 `certs` 資料夾中的憑證檔案名稱。
+ 

**檢查連接至該物件資源的政策**  
當憑證驗證您的裝置時， AWS IoT 政策會允許裝置執行 AWS IoT 操作，例如訂閱或發佈至 MQTT 預留主題。

  如要檢查是否已連接正確的政策：

  1. 如先前所述尋找憑證，然後選擇 **Policies** (政策)。

  1. 選擇顯示的政策，並檢查其是否說明了授予裝置發佈和訂閱 MQTT 預留主題之許可權限的 `connect`、`subscribe`、`receive` 和 `publish` 動作。

     若是範例政策，請參閱 [步驟 1：建立 Device Shadow AWS IoT 的政策](shadow-provision-cloud.md#create-policy-shadow)。

  如果您看到錯誤訊息指出無法連線至 AWS IoT，這可能是因為您用於政策的許可。如果是這種情況，我們建議您從提供 AWS IoT 資源完整存取權的政策開始，然後重新執行範例程式。您可編輯目前的政策，或選擇目前的政策，選擇 **Detach** (分離)，然後建立另一個提供完整存取權的政策，並將其連接至您的物件資源。您可於稍後將政策限制為僅執行程式所需的動作和政策。  
****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:*"
            ],
            "Resource": "*"
        }
    ]
  }
  ```
+ 

**檢查您的裝置 SDK 安裝**  
若程式仍然無法執行，您可重新安裝裝置 SDK，以確定您的 SDK 安裝完整且正確。

## 步驟 4：檢閱結果及後續步驟
<a name="sample-app-shadow-review"></a>

**在本教學課程中，您會了解如何：**
+ 安裝必要的軟體、工具和適用於 Python 的 AWS IoT 裝置 SDK。
+ 了解範例應用程式 `shadow.py` 會如何使用 MQTT 通訊協定來擷取和更新影子的目前狀態。
+ 執行 Device Shadows 的範例應用程式，並在 AWS IoT 主控台中觀察 Shadow 文件的更新。您還會了解在執行程式時如何疑難排解任何問題並修復錯誤。

**後續步驟**  
您現在可以執行 `shadow.py` 範例應用程式，並使用 Device Shadows 來控制狀態。您可以觀察 AWS IoT 主控台中 Shadow 文件的更新，並觀察範例應用程式回應的差異事件。使用 MQTT 測試用戶端，您可以訂閱預留的影子主題，並在執行範例程式時觀察主題所收到的訊息。如需如何執行本教學課程的詳細資訊，請參閱 [教學課程：使用範例應用程式和 MQTT 測試用戶端，與 Device Shadow 互動](interact-lights-device-shadows.md)。

# 教學課程：使用範例應用程式和 MQTT 測試用戶端，與 Device Shadow 互動
<a name="interact-lights-device-shadows"></a>

如要與 `shadow.py` 範例應用程式產生互動，請為 `desired` 值在終端機中輸入一個值。例如，您可以指定類似流量燈的顏色，並 AWS IoT 回應請求並更新報告的值。

**於本教學課程中，您會了解如何：**
+ 使用 `shadow.py` 範例應用程式來指定所需的狀態並更新影子的目前狀態。
+ 編輯 Shadow 文件，以觀察差異事件，及 `shadow.py` 範例應用程序如何加以回應。
+ 使用 MQTT 測試用戶端訂閱影子主題，並在執行範例程式時觀察更新。

**執行本教學課程之前，您必須具備：**  
設定您的 AWS 帳戶、設定您的 Raspberry Pi 裝置，並建立 AWS IoT 物件和政策。您也必須安裝了必要的軟體、裝置 SDK、憑證檔案，並在終端機中執行範例程式。如需詳細資訊，請參閱先前的教學課程 [教學課程：準備好 Raspberry Pi 來執行影子應用程式](create-resources-shadow.md) 和 [步驟 1：執行 shadow.py 範例應用程式](lightbulb-shadow-application.md#run-sample-application-shadows)。若您尚未完成，您必須完成這些教學課程。

**Topics**
+ [步驟 1：使用 `shadow.py` 範例應用程式更新所需和回報的值](#update-desired-shadow-sample)
+ [步驟 2：檢視 MQTT 測試用戶端中 `shadow.py` 範例應用程式的訊息](#shadow-sample-view-msg)
+ [步驟 3：疑難排解 Device Shadow 互動的錯誤](#shadow-observe-messages-troubleshoot)
+ [步驟 4：檢閱結果及後續步驟](#sample-shadow-review)

此教學課程約需 45 分鐘方能完成。

## 步驟 1：使用 `shadow.py` 範例應用程式更新所需和回報的值
<a name="update-desired-shadow-sample"></a>

在先前的教學課程中[步驟 1：執行 shadow.py 範例應用程式](lightbulb-shadow-application.md#run-sample-application-shadows)，您已了解如何在輸入所需的值時，觀察在 AWS IoT 主控台中發佈至 Shadow 文件的訊息，如 一節所述[教學課程：安裝裝置 SDK 並執行 Device Shadows 的範例應用程式](lightbulb-shadow-application.md)。

在上一個範例中，我們將所需的顏色設定為 `yellow`。輸入每個值後，終端機會提示您輸入另一個 `desired` 值。若您再次輸入相同的值 (`yellow`)，應用程序會辨識這一點，並提示您輸入新的 `desired` 值。

```
Enter desired value:
yellow
Local value is already 'yellow'.
Enter desired value:
```

現在，假設您輸入顏色 `green`。 AWS IoT 會回應請求，並將`reported`值更新為 `green`。當 `desired` 狀態與 `reported` 狀態不同而造成差異時，這就是更新發生了。

**`shadow.py` 範例應用程式如何模擬 Device Shadow 互動：**

1. 於終端機中輸入 `desired` 值 (例如 `yellow`)以發布所需的狀態。

1. 由於 `desired` 狀態與 `reported` 狀態 (例如，顏色 `green`) 不同，就會發生差異，而訂閱差異的應用程式會收到這個訊息。

1. 應用程式會回應訊息，並將其狀態更新為 `desired` 值，`yellow`。

1. 然後，應用程式會發佈更新訊息，其包含裝置狀態 `yellow` 的新回報值。

下列展示了終端機中顯示的訊息，其中顯示如何發佈更新請求。

```
Enter desired value:
green
Changed local shadow value to 'green'.
Updating reported shadow value to 'green'...
Update request published.
Finished updating reported shadow value to 'green'.
```

在 AWS IoT 主控台中，Shadow 文件會將 `reported`和 `desired` 欄位`green`的更新值反映至 ，而版本編號會遞增 1。例如，若先前的版本編號顯示為 10，則目前的版本編號會顯示為 11。

**注意**  
刪除影子不會將版本編號重置為 0。當您發佈更新請求或建立另一個具相同名稱的陰子時，您會看到陰子版本會遞增 1。

**編輯 Shadow 文件以觀察差異事件**  
`shadow.py` 範例應用程式也會訂閱 `delta` 事件，並在 `desired` 值發生變更時加以回應。例如，您可將 `desired` 值變更為顏色 `red`。若要這樣做，請在 AWS IoT 主控台中，按一下編輯來**編輯** Shadow 文件，然後在 JSON `red` 中將`desired`值設定為 ，同時將`reported`值保留為 `green`。儲存變更之前，請讓 Raspberry Pi 上的終端機保持開啟狀態，因為您會在變更發生時看到顯示於終端機中的訊息。

```
{
"desired": {
  "welcome": "aws-iot",
  "color": "red"
},
"reported": {
  "welcome": "aws-iot",
  "color": "green"
}
}
```

儲存新值之後，`shadow.py` 範例應用程式會回應此變更，並在終端機中顯示指出差異的訊息。接著，您應該會在輸入 `desired` 值的提示下方看到下列訊息。

```
Enter desired value:
Received shadow delta event.
Delta reports that desired value is 'red'. Changing local value...
Changed local shadow value to 'red'.
Updating reported shadow value to 'red'...
Finished updating reported shadow value to 'red'.
Enter desired value:
Update request published.
Finished updating reported shadow value to 'red'.
```

## 步驟 2：檢視 MQTT 測試用戶端中 `shadow.py` 範例應用程式的訊息
<a name="shadow-sample-view-msg"></a>

您可使用 **AWS IoT 主控台**中的 **MQTT 測試用戶端**，監控傳入您 AWS 帳戶中的 MQTT 訊息。訂閱 Device Shadow 服務使用的預留 MQTT 主題，您可在執行範例應用程式時觀察主題收到的訊息。

若您尚未使用 MQTT 測試用戶端，您可檢閱 [使用 MQTT 用戶端檢視 AWS IoT MQTT 訊息](view-mqtt-messages.md)。這有助於您了解如何使用 **AWS IoT 主控台**中的 **MQTT 測試用戶端**，在 MQTT 訊息通過訊息代理程式時，檢視訊息。

1. 

**開啟 MQTT 測試用戶端**

   在新視窗開啟 [AWS IoT 主控台中的 MQTT 測試用戶端](https://console.aws.amazon.com//iot/home#/test)，如此您便可觀察 MQTT 主題所收到的訊息，不會遺失 MQTT 測試用戶端的組態。若您讓 MQTT 用戶端前往主控台中的另一個頁面，其不會保留任何訂閱或訊息記錄。在教學課程的本節中，您可以讓 AWS IoT 物件的 Shadow 文件和 MQTT 測試用戶端在不同的視窗中開啟，以更輕鬆地觀察與 Device Shadows 的互動。

1. 

**訂閱 MQTT 預留的 Shadow 主題**

   您可使用 MQTT 測試用戶端輸入 Device Shadow 之 MQTT 預留主題的名稱，並加以訂閱，以於執行 `shadow.py` 範例應用程式時收到更新。如要訂閱主題：

   1. 於 **AWS IoT 主控台**的 **MQTT 測試用戶端**中，選擇 **Subscribe to a topic** (訂閱主題)。

   1.  於 **主題篩選條件**區段中，輸入：**\$1aws/things/*thingname*/shadow/update/\$1**。在此，`thingname` 是您先前所建立物件資源的名稱 (例如，`My_light_bulb`)。

   1. 保留其他組態設定的預設值，然後選擇 **Subscribe** (訂閱)。

   在主題訂閱中使用 **\$1** 萬用字元，您可同時訂閱多個 MQTT 主題，並在單一視窗中觀察裝置及其 Shadow 間交換的所有訊息。如需萬用字元及其用法的詳細資訊，請參閱 [MQTT 主題](topics.md)。

1. 

**執行 `shadow.py` 範例程式並觀察訊息**

   在 Raspberry Pi 的命令列視窗中，若您已中斷程式的連線，請再次執行範例應用程式，並於 **AWS IoT 主控台**中查看 **MQTT 測試用戶端**中的訊息。

   1. 執行下列命令以重新啟動範例程式。將 *your-iot-thing-name* 和 *your-iot-endpoint* 取代為您先前建立的 AWS IoT 物件名稱 （例如 `My_light_bulb`)，以及要與裝置互動的端點。

      ```
      cd ~/aws-iot-device-sdk-python-v2/samples/service-clients
      python3 shadow.py --ca_file ~/certs/Amazon-root-CA-1.pem --cert ~/certs/device.pem.crt --key ~/certs/private.pem.key --endpoint your-iot-endpoint --thing_name your-iot-thing-name
      ```

      `shadow.py` 範例應用程式接著會執行並擷取目前的影子狀態。若您已刪除影子或清除目前狀態，該程式會將目前值設定為 `off`，然後提示您輸入 `desired` 值。

      ```
      Connecting to a3qEXAMPLEffp-ats.iot.us-west-2.amazonaws.com with client ID 'test-0c8ae2ff-cc87-49d2-a82a-ae7ba1d0ca5a'...
      Connected!
      Subscribing to Delta events...
      Subscribing to Update responses...
      Subscribing to Get responses...
      Requesting current shadow state...
      Launching thread to read user input...
      Finished getting initial shadow state.
      Shadow document lacks 'color' property. Setting defaults...
      Changed local shadow value to 'off'.
      Updating reported shadow value to 'off'...
      Update request published.
      Finished updating reported shadow value to 'off'...
      Enter desired value:
      ```

      另一方面，若程式正在執行，而您將其重新啟動，則會在終端機中看到回報的最新顏色值。於 MQTT 測試用戶端中，您會看到主題更新 **\$1aws/things/*thingname*/shadow/get** 和 **\$1aws/things/*thingname*/shadow/get/accepted**。

      假設回報的最新顏色是 `green`。下列會顯示 **\$1aws/things/*thingname*/shadow/get/accepted** JSON 檔案的內容。

      ```
      {
      "state": {
        "desired": {
          "welcome": "aws-iot",
          "color": "green"
        },
        "reported": {
          "welcome": "aws-iot",
          "color": "green"
        }
      },
      "metadata": {
        "desired": {
          "welcome": {
            "timestamp": 1620156892
          },
          "color": {
            "timestamp": 1620161643
          }
        },
        "reported": {
          "welcome": {
            "timestamp": 1620156892
          },
          "color": {
            "timestamp": 1620161643
          }
        }
      },
      "version": 10,
      "timestamp": 1620173908
      }
      ```

   1. 於終端機中輸入 `desired` 值，例如 `yellow`。`shadow.py` 範例應用程式會在終端機中回應並顯示下列訊息，顯示 `reported` 值變更為 `yellow`。

      ```
      Enter desired value:
      yellow
      Changed local shadow value to 'yellow'.
      Updating reported shadow value to 'yellow'...
      Update request published.
      Finished updating reported shadow value to 'yellow'.
      ```

      於 **AWS IoT console (主控台)** **MQTT test client (MQTT 測試用戶端)** 的 **Subscriptions (訂閱)** 之下，您會看到下列主題收到訊息：
      + **\$1aws/things/*thingname*/shadow/update**：顯示 `desired` 和 `updated` 值會變更為顏色 `yellow`。
      + **\$1aws/things/*thingname*/shadow/update/accepted**：顯示 `desired` 和 `reported` 狀態的目前值及其中繼資料和版本資訊。
      + **\$1aws/things/*thingname*/shadow/update/documents**：顯示 `desired` 和 `reported` 狀態的先前的值和目前值及其中繼資料和版本資訊。

      作為文件 **\$1aws/things/*thingname*/shadow/update/documents** 也包含其他兩個主題中所包含的資訊，我們可以加以檢閱以查看狀態資訊。先前狀態會顯示設定為 `green` 的回報值、其中繼資料和版本資訊，目前狀態會顯示已更新為 `yellow` 的回報值。

      ```
      {
      "previous": {
        "state": {
          "desired": {
            "welcome": "aws-iot",
            "color": "green"
          },
          "reported": {
            "welcome": "aws-iot",
            "color": "green"
          }
        },
        "metadata": {
          "desired": {
            "welcome": {
              "timestamp": 1617297888
            },
            "color": {
              "timestamp": 1617297898
            }
          },
          "reported": {
            "welcome": {
              "timestamp": 1617297888
            },
            "color": {
              "timestamp": 1617297898
            }
          }
        },
        "version": 10
      },
      "current": {
        "state": {
          "desired": {
            "welcome": "aws-iot",
            "color": "yellow"
          },
          "reported": {
            "welcome": "aws-iot",
            "color": "yellow"
          }
        },
        "metadata": {
          "desired": {
            "welcome": {
              "timestamp": 1617297888
            },
            "color": {
              "timestamp": 1617297904
            }
          },
          "reported": {
            "welcome": {
              "timestamp": 1617297888
            },
            "color": {
              "timestamp": 1617297904
            }
          }
        },
        "version": 11
      },
      "timestamp": 1617297904
      }
      ```

   1. 若您現在輸入另一個 `desired` 值，您會看到這些主題所收到 `reported` 值和訊息更新的進一步變更。版本編號也會遞增 1。例如，若您輸入值 `green` 時，先前的狀態會報告值 `yellow`，而目前狀態會報告值 `green`。

1. 

**編輯 Shadow 文件以觀察差異事件**

   如要觀察差異主題的變更，請編輯 AWS IoT 主控台中的 Shadow 文件。例如，您可將 `desired` 值變更為顏色 `red`。若要這樣做，請在 AWS IoT 主控台中選擇**編輯**，然後在 JSON 中將`desired`值設定為紅色，同時將`reported`值設定為 `green`。儲存變更之前，請保持終端開啟狀態，因為您會在終端機中看到回報的差異訊息。

   ```
   {
   "desired": {
     "welcome": "aws-iot",
     "color": "red"
   },
   "reported": {
     "welcome": "aws-iot",
     "color": "green"
   }
   }
   ```

   `shadow.py` 範例應用程式會回應此變更，並在終端機中顯示指出差異的訊息。於 MQTT 測試用戶端中，`update` 主題將會收到一則訊息，顯示 `desired` 和 `reported` 值的變更。

   您也會看到主題 **\$1aws/things/*thingname*/shadow/update/delta** 收到訊息。如要查看訊息，請選擇此列於 **Subscriptions** (訂閱) 之下的主題。

   ```
   {
   "version": 13,
   "timestamp": 1617318480,
   "state": {
     "color": "red"
   },
   "metadata": {
     "color": {
       "timestamp": 1617318480
     }
   }
   }
   ```

## 步驟 3：疑難排解 Device Shadow 互動的錯誤
<a name="shadow-observe-messages-troubleshoot"></a>

當您執行 Shadow 範例應用程式時，您可能會遇到觀察與 Device Shadow 服務互動的問題。

若程式執行成功，並提示您輸入 `desired` 值，您應可使用如前所述的 Shadow 文件和 MQTT 測試用戶端，觀察 Device Shadow 互動。不過，若您無法看到互動，您可檢查下列事項：
+ 

**在 AWS IoT 主控台中檢查物件名稱及其影子**  
若您看不到 Shadow 文件中的訊息，請檢閱命令，並確定其符合 **AWS IoT 主控台**中的物件名稱。您還可依序選擇您的物件名稱和 **Shadows** (影子)，來檢查您是否有經典影子。本教學課程主要著重於與經典影子的互動。

   您也可以確認您使用的裝置已連線至網際網路。於 **AWS IoT 主控台**中，選擇您先前建立的物件，然後選擇 **Interact** (互動)。在物件詳細資訊頁面上，您應會在此處看到訊息：`This thing already appears to be connected.`
+ 

**查看您訂閱的 MQTT 預留主題**  
若您在 MQTT 測試用戶端中看不到訊息，請檢查您訂閱的主題是否已正確格式化。MQTT Device Shadow 主題具有格式 **\$1aws/things/*thingname*/shadow/**，且可能具有 `update`、`get` 或 `delete`，根據您希望對影子執行的動作而定。本教學課程使用主題 **\$1aws/things/*thingname*/shadow/\$1**，因此，在訂閱測試用戶端之**主題篩選條件**部分中的主題時，請確定您已正確輸入。

  當您輸入主題名稱時，請確定 *thingname* 與您先前建立的 AWS IoT 物件名稱相同。您還可訂閱其他 MQTT 主題，查看是否已成功執行更新。例如，您可訂閱主題 **\$1aws/things/*thingname*/shadow/update/rejected**，在更新請求失敗時收到訊息，您便可對連線問題進行偵錯。如需有關預留主題的更多資訊，請參閱 [影子主題](reserved-topics.md#reserved-topics-shadow) 和 [Device Shadow MQTT 主題](device-shadow-mqtt.md)。

## 步驟 4：檢閱結果及後續步驟
<a name="sample-shadow-review"></a>

**在本教學課程中，您會了解如何：**
+ 使用 `shadow.py` 範例應用程式來指定所需的狀態並更新影子的目前狀態。
+ 編輯 Shadow 文件，以觀察差異事件，及 `shadow.py` 範例應用程序如何加以回應。
+ 使用 MQTT 測試用戶端訂閱影子主題，並在執行範例程式時觀察更新。

**後續步驟**  
您可訂閱其他 MQTT 預留主題，以觀察影子應用程式的更新。例如，若您僅訂閱主題 **\$1aws/things/*thingname*/shadow/update/accepted**，則更新成功執行時，您只會看到目前的狀態資訊。

您也可訂閱其他影子主題來偵錯問題，或深入了解 Device Shadow 互動，還可對 Device Shadow 互動的任何問題進行偵錯。如需詳細資訊，請參閱 [影子主題](reserved-topics.md#reserved-topics-shadow) 及 [Device Shadow MQTT 主題](device-shadow-mqtt.md)。

您也可選擇使用命名影子或使用為 LED 與 Raspberry Pi 連接其他的硬體擴展您的應用程式，並使用從終端傳送訊息來觀察其狀態的變化。

如需有關 Device Shadows 服務及在裝置、應用程式和服務中使用服務的詳細資訊，請參閱 [AWS IoT Device Shadow 服務](iot-device-shadows.md)、[在裝置中使用影子](device-shadow-comms-device.md) and [在應用程式和服務中使用影子](device-shadow-comms-app.md)。

# 教學課程：為 建立自訂授權方 AWS IoT Core
<a name="custom-auth-tutorial"></a>

本教學課程示範使用 AWS CLI來建立、驗證和使用自訂身分驗證的步驟。使用本教學課程，您可以選擇性地使用 Postman，藉由使用 HTTP 發佈 API 將資料傳送到 AWS IoT Core 。

本教學課程會向您展示如何建立範例 Lambda 函數，搭配使用 **create-authorizer** 呼叫與啟用的字符簽署，以實作授權和身分驗證邏輯，以及自訂授權方。然後，使用 驗證授權方**test-invoke-authorizer**，最後您可以使用 HTTP 發佈 API AWS IoT Core 將資料傳送至測試 MQTT 主題。範例請求將使用 `x-amz-customauthorizer-name` 標頭指定要叫用的授權方，並以請求標頭傳遞 token-key-name 和 `x-amz-customauthorizer-signature`。

**您會在本教學課程中學到什麼：**
+ 如何將 Lambda 函數建立為自訂授權方處理常式
+ 如何使用啟用字符簽署 AWS CLI 的 建立自訂授權方
+ 如何使用 **test-invoke-authorizer** 命令測試您的自訂授權方
+ 如何使用[Postman](https://www.postman.com/) 發佈 MQTT 主題，以及如何利用您的自訂授權方驗證請求

此教學課程約需 60 分鐘方能完成。

**Topics**
+ [步驟 1：為自訂授權方建立 Lambda 函數](#custom-auth-tutorial-define)
+ [步驟 2：為自訂授權方建立公有和私有金鑰對](#custom-auth-tutorial-keys)
+ [步驟 3：建立自訂授權方資源及其授權](#custom-auth-tutorial-authorizer)
+ [步驟 4：呼叫 test-invoke-authorizer 來測試授權方](#custom-auth-tutorial-test)
+ [步驟 5：使用 Postman 測試發佈 MQTT 郵件](#custom-auth-tutorial-postman)
+ [步驟 6：在 MQTT 測試用戶端中檢視訊息](#custom-auth-tutorial-testclient)
+ [步驟 7：檢閱結果及後續步驟](#custom-auth-tutorial-review)
+ [步驟 8：清理](#custom-auth-tutorial-cleanup)

**開始本教學課程之前，請確定您有：**
+ 

**[設定 AWS 帳戶](setting-up.md)**  
您需要 AWS 帳戶 和 AWS IoT 主控台才能完成本教學課程。

  當您用於本教學課程的帳戶至少包含這些 AWS 受管政策時，此帳戶最適用：
  + [https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/IAMFullAccess$jsonEditor](https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/IAMFullAccess$jsonEditor)
  + [https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/AWSIoTFullAccess$jsonEditor](https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/AWSIoTFullAccess$jsonEditor)
  + [https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/AWSLambda_FullAccess$jsonEditor](https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/AWSLambda_FullAccess$jsonEditor)
**重要**  
本教學課程中使用的 IAM 政策比您應該在生產實作中遵循的 IAM 政策更寬鬆。在生產環境中，請確定您的帳戶和資源策略僅授予必要的許可。  
當您建立 IAM 政策進行生產時，請判斷使用者和角色需要哪些存取權，然後設計政策，讓使用者只能執行這些任務。  
如需詳細資訊，請參閱 [IAM 中的安全最佳實務](https://docs.aws.amazon.com//IAM/latest/UserGuide/best-practices.html)。
+ 

**已安裝 AWS CLI**  
如需如何安裝 的資訊 AWS CLI，請參閱[安裝 AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/cli-chap-install.html)。本教學課程需要 AWS CLI 版本 `aws-cli/2.1.3 Python/3.7.4 Darwin/18.7.0 exe/x86_64` 或更新版本。
+ 

**OpenSSL 工具**  
本教學課程中的範例使用 [LibreSSL 2.6.5](https://www.libressl.org/)。您也可以針對本教學課程使用 [OpenSSL v1.1.1i](https://www.openssl.org/) 工具。
+ 

**檢閱了 [AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html) 概觀**  
如果您 AWS Lambda 未曾使用過 ，請檢閱[AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html)和[開始使用 Lambda](https://docs.aws.amazon.com//lambda/latest/dg/getting-started.html) 以了解其術語和概念。
+ 

**已檢閱如何在 Postman 中建置請求**  
如需詳細資訊，請參閱[建置請求](https://learning.postman.com/docs/sending-requests/requests/)。
+ 

**已從前一個教學課程中移除自訂授權方**  
您的 一次 AWS 帳戶 只能設定有限數量的自訂授權方。如需如何移除自訂授權方的相關資訊，請參閱 [步驟 8：清理](#custom-auth-tutorial-cleanup)。

## 步驟 1：為自訂授權方建立 Lambda 函數
<a name="custom-auth-tutorial-define"></a>

中的自訂身分驗證 AWS IoT Core 會使用您建立的授權[方資源](https://docs.aws.amazon.com//iot/latest/apireference/API_AuthorizerDescription.html)來驗證和授權用戶端。您將在本節中建立的 函數會在用戶端連線至 和存取 AWS IoT 資源時，進行身分驗證 AWS IoT Core 和授權。

Lambda 函數會執行下列動作：
+ 如果請求來自 **test-invoke-authorizer**，它會傳回一個具有 `Deny` 動作的 IAM 政策。
+ 如果請求來自使用 HTTP 的 Postman，且 `actionToken` 參數的值為 `allow`，則會傳回具有 `Allow`動作的 IAM 政策。否則，它會傳回一個具有 `Deny` 動作的 IAM 政策。

**若要為自訂授權方建立 Lambda 函數**

1. 在 [Lambda](https://console.aws.amazon.com//lambda/home#) 主控台中，開啟 [Functions](https://console.aws.amazon.com//lambda/home#/functions) (函數)。

1. 選擇**建立函數**。

1. 確認已選取 **Author from scratch** (從頭開始撰寫)。

1. 在 **Basic information** (基本資訊) 下：

   1. 在**函數名稱** 中，輸入 **custom-auth-function**。

   1. 在**執行期**中，確認 **Node.js 18.x** 

1. 選擇**建立函數**。

   Lambda 會建立 Node.js 函數和許可函數上傳記錄的[執行角色](https://docs.aws.amazon.com//lambda/latest/dg/lambda-intro-execution-role.html)。當您叫用函數時，Lambda 函數會擔任執行角色，並使用執行角色來建立 AWS SDK 的登入資料，以及從事件來源讀取資料。

1. 若要在 [AWS Cloud9](https://docs.aws.amazon.com/cloud9/latest/user-guide/welcome.html) 編輯器中查看函數的程式碼和組態，請在設計工具視窗中選擇 **custom-auth-function**，然後在編輯器的導覽窗格中選擇 **index.js**。

   對於指令碼語言 (例如 Node.js)，Lambda 包含可傳回成功回應的基本函數。您可以使用 [AWS Cloud9](https://docs.aws.amazon.com/cloud9/latest/user-guide/welcome.html) 編輯器來編輯函數，只要原始碼不超過 3 MB。

1. 將編輯器中的 **index.js** 程式碼取代為下列程式碼：

   ```
   // A simple Lambda function for an authorizer. It demonstrates
   // How to parse a CLI and Http password to generate a response.
   
   export const handler = async (event, context, callback) => {
   
       //Http parameter to initiate allow/deny request
       const HTTP_PARAM_NAME='actionToken';
       const ALLOW_ACTION = 'Allow';
       const DENY_ACTION = 'Deny';
   
       //Event data passed to Lambda function
       var event_str = JSON.stringify(event);
       console.log('Complete event :'+ event_str);
   
       //Read protocolData from the event json passed to Lambda function
       var protocolData = event.protocolData;
       console.log('protocolData value---> ' + protocolData);
   
       //Get the dynamic account ID from function's ARN to be used
       // as full resource for IAM policy
       var ACCOUNT_ID = context.invokedFunctionArn.split(":")[4];
       console.log("ACCOUNT_ID---"+ACCOUNT_ID);
   
       //Get the dynamic region from function's ARN to be used
       // as full resource for IAM policy
       var REGION = context.invokedFunctionArn.split(":")[3];
       console.log("REGION---"+REGION);
   
       //protocolData data will be undefined if testing is done via CLI.
       // This will help to test the set up.
       if (protocolData === undefined) {
   
           //If CLI testing, pass deny action as this is for testing purpose only.
           console.log('Using the test-invoke-authorizer cli for testing only');
           callback(null, generateAuthResponse(DENY_ACTION,ACCOUNT_ID,REGION));
   
       } else{
   
           //Http Testing from Postman
           //Get the query string from the request
           var queryString = event.protocolData.http.queryString;
           console.log('queryString values -- ' + queryString);
           /*         global URLSearchParams       */
           const params = new URLSearchParams(queryString);
           var action = params.get(HTTP_PARAM_NAME);
   
           if(action!=null && action.toLowerCase() === 'allow'){
   
               callback(null, generateAuthResponse(ALLOW_ACTION,ACCOUNT_ID,REGION));
   
           }else{
   
               callback(null, generateAuthResponse(DENY_ACTION,ACCOUNT_ID,REGION));
   
           }
   
       }
   
   };
   
   // Helper function to generate the authorization IAM response.
   var generateAuthResponse = function(effect,ACCOUNT_ID,REGION) {
   
       var full_resource = "arn:aws:iot:"+ REGION + ":" + ACCOUNT_ID + ":*";
       console.log("full_resource---"+full_resource);
   
       var authResponse = {};
       authResponse.isAuthenticated = true;
       authResponse.principalId = 'principalId';
   
       var policyDocument = {};
       policyDocument.Version = '2012-10-17';		 	 	 
       policyDocument.Statement = [];
       var statement = {};
       statement.Action = 'iot:*';
       statement.Effect = effect;
       statement.Resource = full_resource;
       policyDocument.Statement[0] = statement;
       authResponse.policyDocuments = [policyDocument];
       authResponse.disconnectAfterInSeconds = 3600;
       authResponse.refreshAfterInSeconds = 600;
   
       console.log('custom auth policy function called from http');
       console.log('authResponse --> ' + JSON.stringify(authResponse));
       console.log(authResponse.policyDocuments[0]);
   
       return authResponse;
   }
   ```

1. 選擇**部署**。

1. 在 **Changes deployed** (已部署變更) 出現在編輯器上方之後：

   1. 捲動至編輯器上方的 **Function overview** (函數概觀) 區段。

   1. 複製 **Function ARN** (函數 ARN) 並加以儲存，以便稍後可在本教學課程中使用。

1. 測試您的函數

   1. 選擇 **Test** (測試) 標籤。

   1. 使用預設測試設定，選擇 **Invoke** (叫用)。

   1. 如果測試成功，請在 **Execution results** (執行結果) 下，開啟 **Details** (詳細資訊) 檢視。您應該會看到函數傳回的政策文件。

      如果測試失敗或看不到政策文件，請檢閱程式碼以尋找並更正錯誤。

## 步驟 2：為自訂授權方建立公有和私有金鑰對
<a name="custom-auth-tutorial-keys"></a>

您的自訂授權方需要公有和私有金鑰來驗證它。本節中的命令會使用 OpenSSL 工具來建立此金鑰對。

**若要為自訂授權方建立公有和私有金鑰對**

1. 建立私有金鑰檔案。

   ```
   openssl genrsa -out private-key.pem 4096
   ```

1. 驗證您剛建立的私有金鑰檔案。

   ```
   openssl rsa -check -in private-key.pem -noout
   ```

   如果命令未顯示任何錯誤，則私有金鑰檔案是有效的。

1. 建立公有金鑰檔案。

   ```
   openssl rsa -in private-key.pem -pubout -out public-key.pem
   ```

1. 驗證公有金鑰檔案。

   ```
   openssl pkey -inform PEM -pubin -in public-key.pem -noout
   ```

   如果命令未顯示任何錯誤，則公有金鑰檔案是有效的。

## 步驟 3：建立自訂授權方資源及其授權
<a name="custom-auth-tutorial-authorizer"></a>

 AWS IoT 自訂授權方是將先前步驟中建立的所有元素連結在一起的資源。在本節中，您將建立自訂授權方資源，並許可其執行您先前建立的 Lambda 函數。您可以使用 AWS IoT 主控台 AWS CLI、 或 AWS API 來建立自訂授權方資源。

在本教學課程中，您只需建立一個自訂授權方即可。本節說明如何使用 AWS IoT 主控台和 建立 AWS CLI，讓您可以使用最方便的方法。由任一種方法建立的自訂授權方資源之間沒有任何差異。

### 建立自訂授權方資源
<a name="custom-auth-tutorial-authorizer-resource"></a>

**選擇其中一個選項，來建立自訂授權方資源**
+ [使用 AWS IoT 主控台建立自訂授權方](#create-custom-auth-in-console)
+ [使用 AWS CLI建立自訂授權方](#create-custom-auth-in-cli)

**若要建立自訂授權方 (主控台)**

1. 開啟[AWS IoT 主控台的自訂授權方頁面](https://console.aws.amazon.com//iot/home#/authorizerhub)，然後選擇**建立授權方**。

1. 在**建立授權方**中：

   1. 在**授權方名稱**中，輸入 **my-new-authorizer**。

   1. 在**授權方狀態**中，勾選**作用中**。

   1. 在 **Authorizer function** (授權方函數) 中，選擇您先前建立的 Lambda 函數。

   1. 在 **Token validation - optional** (字符驗證 - 選用) 中：

      1. 切換**字符驗證**。

      1. 在**符記金鑰名稱**中，輸入 **tokenKeyName**。

      1. 選擇 **Add key (新增金鑰)**。

      1. 在**金鑰名稱**中，輸入 **FirstKey**。

      1. 在**公有金鑰**中，輸入 `public-key.pem` 檔案的內容。務必包括檔案中具有 `-----BEGIN PUBLIC KEY-----` 和 `-----END PUBLIC KEY-----` 的字行，並且不得從檔案內容中新增或刪除任何換行字元、歸位字元或其他字元。您輸入的字串應該看起來與這個範例相似。

         ```
         -----BEGIN PUBLIC KEY-----
         MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvEBzOk4vhN+3LgslvEWt
         sLCqNmt5Damas3bmiTRvq2gjRJ6KXGTGQChqArAJwL1a9dkS9+maaXC3vc6xzx9z
         QPu/vQOe5tyzz1MsKdmtFGxMqQ3qjEXAMPLEOmqyUKPP5mff58k6ePSfXAnzBH0q
         lg2HioefrpU5OSAnpuRAjYKofKjbc2Vrn6N2G7hV+IfTBvCElf0csalS/Rk4phD5
         oa4Y0GHISRnevypg5C8n9Rrz91PWGqP6M/q5DNJJXjMyleG92hQgu1N696bn5Dw8
         FhedszFa6b2x6xrItZFzewNQkPMLMFhNrQIIyvshtT/F1LVCS5+v8AQ8UGGDfZmv
         QeqAMAF7WgagDMXcfgKSVU8yid2sIm56qsCLMvD2Sq8Lgzpey9N5ON1o1Cvldwvc
         KrJJtgwW6hVqRGuShnownLpgG86M6neZ5sRMbVNZO8OzcobLngJ0Ibw9KkcUdklW
         gvZ6HEJqBY2XE70iEXAMPLETPHzhqvK6Ei1HGxpHsXx6BNft582J1VpgYjXha8oa
         /NN7l7Zbj/euAb41IVtmX8JrD9z613d1iM5L8HluJlUzn62Q+VeNV2tdA7MfPfMC
         8btGYladFAnitThaz6+F0VSBJPu7pZQoLnqyEp5zLMtF+kFl2yOBmGAP0RBivRd9
         JWBUCG0bqcLQPeQyjbXSOfUCAwEAAQ==
         -----END PUBLIC KEY-----
         ```

1. 選擇 **Create Authorizer** (建立授權方)。

1. 如果已建立自訂授權方資源，您會看到自訂授權方的清單，而且您的新自訂授權方應該會出現在清單中，接著您可以繼續進行下一節來測試它。

   如果您看到錯誤，請檢閱錯誤並嘗試重新建立您的自訂授權方，然後再次檢查這些項目。請注意，每個自訂授權方資源都必須具有唯一名稱。

**建立自訂授權方 (AWS CLI)**

1. 將您的值替代為 `authorizer-function-arn` 和 `token-signing-public-keys`，然後執行下列命令：

   ```
   aws iot create-authorizer \
   --authorizer-name "my-new-authorizer" \
   --token-key-name "tokenKeyName" \
   --status ACTIVE \
   --no-signing-disabled \
   --authorizer-function-arn "arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function" \
   --token-signing-public-keys FirstKey="-----BEGIN PUBLIC KEY-----
   MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvEBzOk4vhN+3LgslvEWt
   sLCqNmt5Damas3bmiTRvq2gjRJ6KXGTGQChqArAJwL1a9dkS9+maaXC3vc6xzx9z
   QPu/vQOe5tyzz1MsKdmtFGxMqQ3qjEXAMPLEOmqyUKPP5mff58k6ePSfXAnzBH0q
   lg2HioefrpU5OSAnpuRAjYKofKjbc2Vrn6N2G7hV+IfTBvCElf0csalS/Rk4phD5
   oa4Y0GHISRnevypg5C8n9Rrz91PWGqP6M/q5DNJJXjMyleG92hQgu1N696bn5Dw8
   FhedszFa6b2x6xrItZFzewNQkPMLMFhNrQIIyvshtT/F1LVCS5+v8AQ8UGGDfZmv
   QeqAMAF7WgagDMXcfgKSVU8yid2sIm56qsCLMvD2Sq8Lgzpey9N5ON1o1Cvldwvc
   KrJJtgwW6hVqRGuShnownLpgG86M6neZ5sRMbVNZO8OzcobLngJ0Ibw9KkcUdklW
   gvZ6HEJqBY2XE70iEXAMPLETPHzhqvK6Ei1HGxpHsXx6BNft582J1VpgYjXha8oa
   /NN7l7Zbj/euAb41IVtmX8JrD9z613d1iM5L8HluJlUzn62Q+VeNV2tdA7MfPfMC
   8btGYladFAnitThaz6+F0VSBJPu7pZQoLnqyEp5zLMtF+kFl2yOBmGAP0RBivRd9
   JWBUCG0bqcLQPeQyjbXSOfUCAwEAAQ==
   -----END PUBLIC KEY-----"
   ```

**其中：**
   + `authorizer-function-arn` 值是您為自訂授權方建立之 Lambda 函數的 Amazon 資源名稱 (ARN)。
   +  `token-signing-public-keys` 值包含金鑰的名稱 **FirstKey** 以及 `public-key.pem` 檔案的內容 務必包括檔案中具有 `-----BEGIN PUBLIC KEY-----` 和 `-----END PUBLIC KEY-----` 的字行，並且不得從檔案內容中新增或刪除任何換行字元、歸位字元或其他字元。

     注意：輸入公有金鑰時要小心，因為公有金鑰值若有任何更改，都會使其無法使用。

1. 如果已建立自訂授權方，則命令會傳回新資源的名稱和 ARN，如下所示。

   ```
   {
       "authorizerName": "my-new-authorizer",
       "authorizerArn": "arn:aws:iot:Region:57EXAMPLE833:authorizer/my-new-authorizer"
   }
   ```

   儲存 `authorizerArn` 值，以便用於下一個步驟。

   記住，每個自訂授權方資源都必須具有唯一名稱。

### 授權自訂授權方資源
<a name="custom-auth-tutorial-authorizer-permission"></a>

在本節中，您將許可您剛建立的自訂授權方資源執行 Lambda 函數。若要授與許可，您可以使用 [add-permission](https://docs.aws.amazon.com//cli/latest/reference/lambda/add-permission.html) CLI 命令。

**使用 將許可授予 Lambda 函數 AWS CLI**

1. 在插入您的值之後，輸入以下命令。請注意，`statement-id` 值必須是唯一的。如果您之前已執行本教學課程，或者如果您得到 `ResourceConflictException` 錯誤，請將 `Id-1234` 取代為另一個值，。

   ```
   aws lambda add-permission  \
   --function-name "custom-auth-function" \
   --principal "iot.amazonaws.com" \
   --action "lambda:InvokeFunction" \
   --statement-id "Id-1234" \
   --source-arn authorizerArn
   ```

1. 如果命令成功，它會傳回許可陳述式，例如此範例。您可以繼續下一節來測試自訂授權方。

   ```
   {
       "Statement": "{\"Sid\":\"Id-1234\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"iot.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function\"}}}"
   }
   ```

   如果命令未成功，它會傳回錯誤，例如此範例。您必須先檢閱並更正錯誤，然後才能繼續進行。

   ```
   An error occurred (AccessDeniedException) when calling the AddPermission operation: User: arn:aws:iam::57EXAMPLE833:user/EXAMPLE-1 is not authorized to perform: lambda:AddPer
   mission on resource: arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function
   ```

## 步驟 4：呼叫 test-invoke-authorizer 來測試授權方
<a name="custom-auth-tutorial-test"></a>

定義所有資源後，在本節中，您會從命令列呼叫 test-invoke-authorizer 來測試授權是否通過。

請注意，從命令列叫用授權方時，未定義 `protocolData`，因此授權方將一律傳回 DENY 文件。不過，此測試會確認您的自訂授權方和 Lambda 函數已正確設定，即使它未完全測試 Lambda 函數也一樣。

**使用 測試您的自訂授權方及其 Lambda 函數 AWS CLI**

1. 在具有您在前一個步驟中建立之 `private-key.pem` 檔案的目錄中，執行下列命令。

   ```
   echo -n "tokenKeyValue" | openssl dgst -sha256 -sign private-key.pem | openssl base64 -A
   ```

   此命令會建立要在下一個步驟中使用的簽章字串。簽章字串看起來像這樣：

   ```
   dBwykzlb+fo+JmSGdwoGr8dyC2qB/IyLefJJr+rbCvmu9Jl4KHAA9DG+V+MMWu09YSA86+64Y3Gt4tOykpZqn9mn
   VB1wyxp+0bDZh8hmqUAUH3fwi3fPjBvCa4cwNuLQNqBZzbCvsluv7i2IMjEg+CPY0zrWt1jr9BikgGPDxWkjaeeh
   bQHHTo357TegKs9pP30Uf4TrxypNmFswA5k7QIc01n4bIyRTm90OyZ94R4bdJsHNig1JePgnuOBvMGCEFE09jGjj
   szEHfgAUAQIWXiVGQj16BU1xKpTGSiTAwheLKUjITOEXAMPLECK3aHKYKY+d1vTvdthKtYHBq8MjhzJ0kggbt29V
   QJCb8RilN/P5+vcVniSXWPplyB5jkYs9UvG08REoy64AtizfUhvSul/r/F3VV8ITtQp3aXiUtcspACi6ca+tsDuX
   f3LzCwQQF/YSUy02u5XkWn+sto6KCkpNlkD0wU8gl3+kOzxrthnQ8gEajd5Iylx230iqcXo3osjPha7JDyWM5o+K
   EWckTe91I1mokDr5sJ4JXixvnJTVSx1li49IalW4en1DAkc1a0s2U2UNm236EXAMPLELotyh7h+flFeloZlAWQFH
   xRlXsPqiVKS1ZIUClaZWprh/orDJplpiWfBgBIOgokJIDGP9gwhXIIk7zWrGmWpMK9o=
   ```

   複製此簽章字串以在下一個步驟中使用。請小心不要包含任何額外的字元或留下任何額外的字元。

1. 在此命令中，會將 `token-signature` 值取代為來自前一個步驟的簽章字串，並執行此命令來測試您的授權方。

   ```
   aws iot test-invoke-authorizer \
   --authorizer-name my-new-authorizer \
   --token tokenKeyValue \
   --token-signature dBwykzlb+fo+JmSGdwoGr8dyC2qB/IyLefJJr+rbCvmu9Jl4KHAA9DG+V+MMWu09YSA86+64Y3Gt4tOykpZqn9mnVB1wyxp+0bDZh8hmqUAUH3fwi3fPjBvCa4cwNuLQNqBZzbCvsluv7i2IMjEg+CPY0zrWt1jr9BikgGPDxWkjaeehbQHHTo357TegKs9pP30Uf4TrxypNmFswA5k7QIc01n4bIyRTm90OyZ94R4bdJsHNig1JePgnuOBvMGCEFE09jGjjszEHfgAUAQIWXiVGQj16BU1xKpTGSiTAwheLKUjITOEXAMPLECK3aHKYKY+d1vTvdthKtYHBq8MjhzJ0kggbt29VQJCb8RilN/P5+vcVniSXWPplyB5jkYs9UvG08REoy64AtizfUhvSul/r/F3VV8ITtQp3aXiUtcspACi6ca+tsDuXf3LzCwQQF/YSUy02u5XkWn+sto6KCkpNlkD0wU8gl3+kOzxrthnQ8gEajd5Iylx230iqcXo3osjPha7JDyWM5o+KEWckTe91I1mokDr5sJ4JXixvnJTVSx1li49IalW4en1DAkc1a0s2U2UNm236EXAMPLELotyh7h+flFeloZlAWQFHxRlXsPqiVKS1ZIUClaZWprh/orDJplpiWfBgBIOgokJIDGP9gwhXIIk7zWrGmWpMK9o=
   ```

   如果命令成功，它會傳回自訂授權方函數產生的資訊，例如此範例。

   ```
   {
       "isAuthenticated": true,
       "principalId": "principalId",
       "policyDocuments": [
           "{\"Version\":\"2012-10-17\",		 	 	 \"Statement\":[{\"Action\":\"iot:*\",\"Effect\":\"Deny\",\"Resource\":\"arn:aws:iot:Region:57EXAMPLE833:*\"}]}"
       ],
       "refreshAfterInSeconds": 600,
       "disconnectAfterInSeconds": 3600
   }
   ```

   如果指令傳回錯誤，請檢閱錯誤並再次檢查您在本節中使用的命令。

## 步驟 5：使用 Postman 測試發佈 MQTT 郵件
<a name="custom-auth-tutorial-postman"></a>

1. 若要從命令列取得您的裝置資料端點，請呼叫 [describe-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iot/describe-endpoint.html)，如這裡所示

   ```
   aws iot describe-endpoint --output text --endpoint-type iot:Data-ATS
   ```

   儲存此地址，以在稍後步驟中用作 *device\$1data\$1endpoint\$1address*。

1. 開啟新的 Postman 視窗並建立新的 HTTP POST 請求。

   1. 從您的電腦中，開啟 Postman 應用程式。

   1. 在 Postman 的 **File** (檔案) 選單中，選擇 **New** (新增)。

   1. 在 **New** (新增) 對話方塊中，選擇 **Request** (請求)。

   1. 在儲存請求中，

      1. 在 **Request name** (請求名稱) 中，輸入 **Custom authorizer test request**。

      1. 在 **Select a collection or folder to save to:** (選取要儲存到哪個集合或資料夾：) 中，選擇或建立要儲存此請求的集合。

      1. 選擇 ** Save to *collection\$1name*** (儲存至 collection\$1name)。

1. 建立 POST 請求來測試您的自訂授權方。

   1. 在 URL 欄位旁邊的請求方法選取器中，選擇 **POST**。

   1. 在 URL 欄位中，為您的請求建立 URL，方法為搭配使用下列 URL 與來自前一個步驟中 [describe-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iot/describe-endpoint.html) 命令的 *device\$1data\$1endpoint\$1address*。

      ```
      https://device_data_endpoint_address:443/topics/test/cust-auth/topic?qos=0&actionToken=allow
      ```

      請注意，此 URL 包含 `actionToken=allow` 查詢參數，它會告訴您的 Lambda 函數傳回允許存取 AWS IoT的政策文件。輸入 URL 之後，查詢參數也會出現在 Postman 的 **Params** (參數) 標籤中。

   1. 在 **Auth** (身分驗證) 標籤的 **Type** (類型) 欄位中，選擇 **No Auth** (無需身分驗證)。

   1. 在標頭標籤中：

      1. 如果有已核取的 **Host** (主機) 金鑰，請取消核取此金鑰。

      1. 在標頭清單的底部，加入這些新標題並確認已核取它們。將 **Host** 值取代為您的 *device\$1data\$1endpoint\$1address*，並將 **x-amz-customauthorizer-signature** 值取代為在上節中與 **test-invoke-authorize** 命令搭配使用的簽章字串。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/custom-auth-tutorial.html)

   1. 在主體標籤中：

      1. 在資料格式選項方塊中，選擇 **Raw** (原始)。

      1. 在資料類型清單中，選擇 **JavaScript**。

      1. 在文字欄位中，為您的測試訊息輸入此 JSON 訊息承載：

         ```
         {
             "data_mode": "test",
             "vibration": 200,
             "temperature": 40
         }
         ```

1. 選擇 **Send** (傳送) 以傳送請求。

   如果請求成功，它會傳回：

   ```
   {
       "message": "OK",
       "traceId": "ff35c33f-409a-ea90-b06f-fbEXAMPLE25c"
   }
   ```

   成功回應表示您的自訂授權方允許與 的連線， AWS IoT 且測試訊息已交付至 中的代理程式 AWS IoT Core。

   如果傳回錯誤，請檢閱錯誤訊息、*device\$1data\$1endpoint\$1address*、簽章字串，以及其他標頭值。

請將此請求保留在 Postman，以供下一節使用。

## 步驟 6：在 MQTT 測試用戶端中檢視訊息
<a name="custom-auth-tutorial-testclient"></a>

在上一個步驟中，您使用 Postman AWS IoT 將模擬裝置訊息傳送到 。成功回應指出您的自訂授權方允許連線到 AWS IoT ，並指出測試訊息已傳遞至 AWS IoT Core中的代理程式。在本節中，您將使用 AWS IoT 主控台中的 MQTT 測試用戶端，以其他裝置和服務可能的方式查看該訊息的訊息內容。

**若要查看自訂授權方所授權的測試訊息**

1. 在 AWS IoT 主控台中，開啟 [MQTT 測試用戶端](https://console.aws.amazon.com//iot/home#/test)。

1. 在 **Subscribe to topic** (訂閱主題) 標籤的 **Topic filter** (主題篩選條件) 中，輸入 **test/cust-auth/topic**，這是前一節的 Postman 範例中使用的訊息主題。

1. 選擇 **Subscribe (訂閱)**。

   保留此視窗讓後續步驟可以看到它。

1. 在 Postman 中，於您為前一節建立的請求中，選擇 **Send** (傳送)。

   檢閱回應以確定回應成功。如果未成功，請依照前一節所述疑難排解錯誤。

1. 在 **MQTT test client** (MQTT 測試用戶端) 中，您應該會看到顯示訊息主題的新項目，而且如果展開的話，則會看到您從 Postman 傳送之請求中的訊息承載。

   如果未在 **MQTT test client** (MQTT 測試用戶端) 中看到您的訊息，以下是一些需要檢查的事項：
   + 確定您的 Postman 請求成功傳回。如果 AWS IoT 拒絕連線並傳回錯誤，則請求中的訊息不會傳遞給訊息中介裝置。
   + 確定 AWS 區域 用來開啟 AWS IoT 主控台的 AWS 帳戶 和 與您在 Postman URL 中使用的 相同。
   + 請確定您使用自訂授權方的適當端點。預設 IoT 端點可能不支援搭配 Lambda 函數使用自訂授權方。反之，您可以使用網域組態來定義新的端點，然後為自訂授權方指定該端點。
   + 確定您已在 **MQTT test client** (MQTT 測試用戶端) 中正確地輸入主題。主題篩選條件會區分大小寫。如有疑問，您也可以訂閱 主題，該**\$1**主題會訂閱傳遞訊息代理程式 AWS 帳戶 並 AWS 區域 用來開啟 AWS IoT 主控台的所有 MQTT 訊息。

## 步驟 7：檢閱結果及後續步驟
<a name="custom-auth-tutorial-review"></a>

**在本教學課程中：**
+ 已將 Lambda 函數建立為自訂授權方處理常式
+ 已在啟用字符簽署的情況下建立自訂授權方
+ 已使用 **test-invoke-authorizer** 命令測試您的自訂授權方
+ 已使用 [Postman](https://www.postman.com/) 發佈 MQTT 主題，並利用您的自訂授權方驗證請求
+ 已使用 **MQTT test client** (MQTT 測試用戶端) 來檢視從 Postman 測試傳送的訊息

**後續步驟**  
從 Postman 傳送一些訊息以驗證自訂授權方是否正在運作之後，請試驗看看變更本教學課程的不同層面如何影響結果。以下是幾個入門範例。
+ 變更簽章字串，以便查看未經授權之連線嘗試的處理方式不再有效。您應該會得到錯誤回應 (例如這個錯誤回應)，且訊息應該不會出現在 **MQTT test client** (MQTT 測試用戶端) 中。

  ```
  {
      "message": "Forbidden",
      "traceId": "15969756-a4a4-917c-b47a-5433e25b1356"
  }
  ```
+ 若要進一步了解如何尋找在您開發和使用 AWS IoT 規則時可能發生的錯誤，請參閱 [監控 AWS IoT](monitoring_overview.md)。

## 步驟 8：清理
<a name="custom-auth-tutorial-cleanup"></a>

如果想要重複本教學課程，您可能需要移除某些自訂授權方。您的 AWS 帳戶 一次只能設定有限數量的自訂授權方，而且當您嘗試新增新的授權方而不移除現有的自訂授權方`LimitExceededException`時，您可以取得 。

**移除自訂授權方 (主控台)**

1. 開啟[AWS IoT 主控台的自訂授權方頁面](https://console.aws.amazon.com//iot/home#/authorizerhub)，然後在自訂授權方清單中，尋找要移除的自訂授權方。

1. 開啟自訂授權方詳細資訊頁面，然後從 **Actions** (動作) 選單中，選擇 **Edit** (編輯)。

1. 取消核取 **Activate authorizer** (啟用授權方)，然後選擇 **Update** (更新)。

   在自訂授權方作用中時，您無法將其刪除。

1. 從自訂授權方詳細資訊頁面中，開啟 **Actions** (動作) 選單，然後選擇 **Delete** (刪除)。

**移除自訂授權方 (AWS CLI)**

1. 列出您已安裝的自訂授權方，並找出要刪除的自訂授權方名稱。

   ```
   aws iot list-authorizers 
   ```

1. 在將 `Custom_Auth_Name` 取代為要刪除之自訂授權方的 `authorizerName` 之後，執行此命令將自訂授權方設定為 `inactive`。

   ```
   aws iot update-authorizer --status INACTIVE --authorizer-name Custom_Auth_Name
   ```

1. 在將 `Custom_Auth_Name` 取代為要刪除之自訂授權方的 `authorizerName` 之後，執行此命令來刪除自訂授權方。

   ```
   aws iot delete-authorizer --authorizer-name Custom_Auth_Name
   ```

# 教學課程：使用 AWS IoT 和 Raspberry Pi 監控土壤濕度
<a name="iot-moisture-tutorial"></a>

本教學課程說明如何使用 [Raspberry Pi](https://www.raspberrypi.org/)、濕度感應器，以及 AWS IoT 監控房屋植物或花園的土壤濕度等級。Raspberry Pi 會執行程式碼，從感應器讀取濕度等級和溫度，然後將資料傳送至其中 AWS IoT。您可以在 中建立規則 AWS IoT ，當濕度等級低於閾值時，將電子郵件傳送至訂閱 Amazon SNS 主題的地址。

**注意**  
本教學課程可能不是最新版本。自本主題最初發佈後，某些參考文件可能已被取代。

**Contents**
+ [先決條件](#iot-moisture-prereqs)
+ [設定 AWS IoT](iot-moisture-setup.md)
  + [步驟 1：建立 AWS IoT 政策](iot-moisture-policy.md)
  + [步驟 2：建立 AWS IoT 物件、憑證和私有金鑰](iot-moisture-create-thing.md)
  + [步驟 3：建立 Amazon SNS 主題與訂閱。](iot-moisture-create-sns-topic.md)
  + [步驟 4：建立 AWS IoT 規則來傳送電子郵件](iot-moisture-create-rule.md)
+ [設定您的 Raspberry Pi 和濕度感應器](iot-moisture-raspi-setup.md)

## 先決條件
<a name="iot-moisture-prereqs"></a>

為完成此教學課程您需要：
+  AWS 帳戶。
+ 擁有管理員許可的 IAM 使用者。
+ 執行 Windows、macOS、Linux 或 Unix 的開發電腦，用來存取 [AWS IoT 主控台](https://console.aws.amazon.com/iot/home)。
+ 執行最新 [Raspberry Pi 作業系統的 Raspberry Pi 3B 或 4B](https://www.raspberrypi.com/products/)。 [https://www.raspberrypi.com/software/operating-systems/](https://www.raspberrypi.com/software/operating-systems/)如需安裝說明，請參閱 Raspberry Pi 網站上的[安裝作業系統](https://www.raspberrypi.com/documentation/computers/getting-started.html#installing-the-operating-system)。
+ 用於 Raspberry Pi 的顯示器、鍵盤、滑鼠和 Wi-Fi 網路或乙太網路連線。
+ 與 Raspberry Pi 相容的濕度感應器。本教學課程中使用的感應器是 [Adafure STEMMA I2C 電容式濕度感應器](https://www.adafruit.com/product/4026)搭配 [JST 4 針腳轉母頭插槽纜線接頭](https://www.adafruit.com/product/3950)。

# 設定 AWS IoT
<a name="iot-moisture-setup"></a>

若要完成此教學課程，您需要建立以下資源。若要將裝置連線至 AWS IoT，您可以建立 IoT 物件、裝置憑證和 AWS IoT 政策。
+ 實 AWS IoT 物。

  代表實體裝置 (在此案例中為 Rasberry Pi)，包含有關裝置的靜態中繼資料的物件。
+ 裝置憑證。

  所有裝置都必須擁有裝置憑證，才能連接至並向 AWS IoT驗證。
+  AWS IoT 政策。

  每個裝置憑證都有一或多個與其相關聯的 AWS IoT 政策。這些政策會決定裝置可存取 AWS IoT 的資源。
+  AWS IoT 根 CA 憑證。

  裝置和其他用戶端使用 AWS IoT 根 CA 憑證來驗證與其通訊的 AWS IoT 伺服器。如需詳細資訊，請參閱[伺服器驗證](server-authentication.md)。
+  AWS IoT 規則。

  規則包含查詢和一或多個規則動作。查詢會從裝置訊息擷取資料，以判斷是否應處理訊息資料。規則動作會指定當資料符合查詢時要採取的動作。
+ Amazon SNS 主題和主題訂閱。

  此規則會監聽來自 Raspberry Pi 的濕度資料。如果值低於閾值，它會將訊息傳送到 Amazon SNS 主題。Amazon SNS 會將該訊息傳送到訂閱該主題的所有電子郵件地址。

 



# 步驟 1：建立 AWS IoT 政策
<a name="iot-moisture-policy"></a>

建立允許 Raspberry Pi 連線和傳送訊息 AWS IoT 的政策 AWS IoT。

1. 在 [AWS IoT 主控台](https://console.aws.amazon.com/iot)中，如果 **Get started (開始)** 按鈕出現，請選擇它。否則，請在導覽窗格中展開 **Security** (安全性)，然後選擇 **Policies (政策)**。

1. 如果 **You don’t have any policies yet (您尚未有任何政策)** 對話方塊出現，請選擇 **Create a policy (建立政策)**。否則，請選擇 **Create** (建立)。

1. 輸入 AWS IoT 政策的名稱 （例如 **MoistureSensorPolicy**)。

1. 在 **Add statements (新增陳述式)** 區段中，將現有政策取代為下列 JSON。以您的 和 AWS 帳戶 號碼取代*區域* AWS 區域 和*帳戶*。  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": "iot:Connect",
               "Resource": "arn:aws:iot:us-east-1:123456789012:client/RaspberryPi"
           },
           {
               "Effect": "Allow",
               "Action": "iot:Publish",
               "Resource": [
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/update",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/delete",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/get"
               ]
           },
           {
               "Effect": "Allow",
               "Action": "iot:Receive",
               "Resource": [
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/update/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/delete/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/get/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/update/rejected",
                   "arn:aws:iot:us-east-1:123456789012:topic/$aws/things/RaspberryPi/shadow/delete/rejected"
               ]
           },
           {
               "Effect": "Allow",
               "Action": "iot:Subscribe",
               "Resource": [
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/update/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/delete/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/get/accepted",
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/update/rejected",
                   "arn:aws:iot:us-east-1:123456789012:topicfilter/$aws/things/RaspberryPi/shadow/delete/rejected"
               ]
           },
           {
               "Effect": "Allow",
               "Action": [
                   "iot:GetThingShadow",
                   "iot:UpdateThingShadow",
                   "iot:DeleteThingShadow"
               ],
               "Resource": "arn:aws:iot:us-east-1:123456789012:thing/RaspberryPi"
           }
       ]
   }
   ```

1. 選擇**建立**。

# 步驟 2：建立 AWS IoT 物件、憑證和私有金鑰
<a name="iot-moisture-create-thing"></a>

在 AWS IoT 登錄檔中建立物件以代表您的 Raspberry Pi。

1. 在 [AWS IoT 主控台](https://console.aws.amazon.com/iot/home)的導覽窗格中，依序選擇 **Manage** (管理) 和 **Things** (物件)。

1. 如果顯示 **You don’t have any things yet (尚無任何物件)** 對話方塊，請選擇 **Register a thing (註冊物件)**。否則，請選擇 **Create** (建立)。

1. 在**建立 AWS IoT 物件**頁面上，選擇**建立單一物件**。

1. 在 **Add your device to the device registry (將裝置新增至裝置登錄檔)** 頁面上，輸入您 IoT 物件的名稱 (例如 **RaspberryPi**)，然後選擇 **Next (下一步)**。您無法在建立之後變更物件的名稱。要變更物件的名稱，您必須建立一個新的物件並為它命名，然後刪除舊的物件。

1. 在 **Add a certificate for your thing (新增物件的憑證)** 頁面上，選擇 **Create certificate (建立憑證)**。

1. 選擇 **Download (下載)** 連結來下載憑證、私有金鑰和根憑證授權機構憑證。
**重要**  
這是您可以下載憑證和私有金鑰唯一機會。

1. 若要啟用憑證，請選擇 **Activate** (啟用)。憑證必須作用中，裝置才能連接到 AWS IoT。

1. 選擇 **Attach a policy (連接政策)**。

1. 針對 **Add a policy for your thing (新增您的物件的政策)**，選擇 **MoistureSensorPolicy**，然後選擇 **Register Thing (註冊物件)**。

# 步驟 3：建立 Amazon SNS 主題與訂閱。
<a name="iot-moisture-create-sns-topic"></a>

建立 Amazon SNS 主題與訂閱。

1. 在 [AWS SNS 主控台](https://console.aws.amazon.com/sns/home)的導覽窗格中，選擇 **Topics** (主題)，然後選擇 **Create topic** (建立主題)。

1. 選擇類型為**標準**，然後輸入主題的名稱 （例如 **MoistureSensorTopic**)。

1. 輸入主題的顯示名稱 (例如，**Moisture Sensor Topic**)。這是在 Amazon SNS 主控台中針對您的主題顯示的名稱。

1. 請選擇**建立主題**。

1. 在 Amazon SNS 主題詳細資訊頁面中，選擇 **Create subscription** (建立訂閱)。

1. 對於**通訊協定**，選擇**電子郵件**。

1. 針對 **Endpoint (端點)**，輸入電子郵件地址。

1. 選擇**建立訂閱**。

1. 開啟您的電子郵件用戶端，並尋找主旨為 **MoistureSensorTopic** 的訊息。開啟電子郵件，然後按一下 **Confirm subscription (確認訂閱)** 連結。
**重要**  
在您確認訂閱之前，不會收到來自此 Amazon SNS 主題的任何電子郵件提醒。

您應該會收到含有您輸入文字的電子郵件訊息。

# 步驟 4：建立 AWS IoT 規則來傳送電子郵件
<a name="iot-moisture-create-rule"></a>

 AWS IoT 規則會定義查詢，以及從裝置接收訊息時要採取的一或多個動作。 AWS IoT 規則引擎會監聽裝置傳送的訊息，並使用訊息中的資料來判斷是否應採取一些動作。如需詳細資訊，請參閱[的規則 AWS IoT](iot-rules.md)。

在此教學中，您的 Raspberry Pi 會將訊息發佈至 `aws/things/RaspberryPi/shadow/update`。這是內部的 MQTT 主題，供裝置和物件影子服務使用。Raspberry Pi 發佈的訊息會具備以下格式：

```
{
    "reported": {
        "moisture" : moisture-reading,
        "temp" : temperature-reading
    }
}
```

您會建立一個查詢，從傳入的訊息擷取濕度和溫度資料。您也可以建立 Amazon SNS 動作，在濕度讀數低於閾值時，取得資料並將其傳送給 Amazon SNS 主題訂閱者。

**建立 Amazon SNS 規則**

1. 在 [AWS IoT 主控台](https://console.aws.amazon.com/iot/home)中，選擇**訊息路由**，然後選擇**規則**。如果 **You don’t have any rules yet (您尚未有任何規則)** 對話方塊出現，請選擇 **Create a rule (建立規則)**。否則，請選擇**建立規則**。

1. 在**規則屬性**頁面中，輸入**規則名稱**，例如 **MoistureSensorRule**，並提供簡短的**規則描述**，例如 **Sends an alert when soil moisture level readings are too low**。

1. 選擇**下一步**並設定 SQL 陳述式。選擇 **SQL 版本**為 **2016-03-23**，然後輸入下列 AWS IoT SQL 查詢陳述式：

   ```
   SELECT * FROM '$aws/things/RaspberryPi/shadow/update/accepted' WHERE state.reported.moisture < 400
   ```

   此陳述式會在 `moisture` 讀數小於 `400` 時觸發規則動作。
**注意**  
您可能需要使用不同的值。在 Raspberry Pi 上執行程式碼之後，您可以碰觸感應器、將其放入水中或將其放入花盆中，以查看從感應器取得的值。

1. 選擇**下一步**並連接規則動作。針對**動作 1**，選擇**簡易通知服務**。此規則動作的描述是**傳送訊息做為 SNS 推送通知**。

1. 針對 **SNS 主題**，選擇您在 [步驟 3：建立 Amazon SNS 主題與訂閱。](iot-moisture-create-sns-topic.md)、**MoistureSensorTopic** 中建立的主題，並將**訊息格式**保留為 **RAW**。對於 **IAM 角色**，選擇**建立新角色**。輸入角色的名稱，例如 **LowMoistureTopicRole**，然後選擇**建立角色**。

1. 選擇**下一步**以檢閱，然後選擇**建立**以建立規則。

# 設定您的 Raspberry Pi 和濕度感應器
<a name="iot-moisture-raspi-setup"></a>



將 microSD 卡插入 Raspberry Pi，連接顯示器、鍵盤、滑鼠，以及乙太網路纜線 (如果未使用 Wi-Fi)。還不要連接電源線。

將 JST 跳線纜線連接至濕度感應器。跳線的另一端有四條配線：
+ 綠色：I2C SCL
+ 白色：I2C SDA
+ 紅色：功率 (3.5 V)
+ 黑色：接地

按住 Raspberry Pi 與右側的乙太網路插孔。在此方向中，上方有兩列 GPIO 接腳。按照以下順序，將濕度感應器的配線連接到接腳的下方排。從最左側接腳開始，連接紅色 (電源)、白色 (SDA) 和綠色 (SCL)。略過一個接腳，然後連接黑色 (接地) 配線。如需詳細資訊，請參閱 [Python Computer Wiring](https://learn.adafruit.com/adafruit-stemma-soil-sensor-i2c-capacitive-moisture-sensor/python-circuitpython-test)。

將電源線連接至 Raspberry Pi，並將另一端插入牆上插座，以將其開啟。

**設定您的 Raspberry Pi**

1. 在 **Welcome to Raspberry Pi (歡迎使用 Raspberry Pi)** 上，選擇 **Next (下一步)**。

1. 選擇您的國家/地區、語言、時區及鍵盤配置。選擇 **Next** (下一步)。

1. 輸入您的 Raspberry Pi 的密碼，然後選擇 **Next (下一步)**。

1. 選擇您的 Wi-Fi 網路，然後選擇 **Next (下一步)**。如果您不是使用 Wi-Fi 網路，請選擇 **Skip (略過)**。

1. 選擇 **Next (下一步)** 以檢查軟體更新。更新完成時，選擇 **Restart (重新啟動)** 以重新啟動您的 Raspberry Pi。

在 Raspberry Pi 啟動後，啟用 I2C 介面。

1. 在 Raspbian 桌面的左上角，按一下 Raspberry 圖示，選擇 **Preferences (偏好設定)**，然後選擇 **Raspberry Pi Configuration (Raspberry Pi 組態)**。

1. 在 **Interfaces (介面)** 標籤上，針對 **I2C**，選擇 **Enable (啟用)**。

1. 選擇**確定**。

Adafruit STEMMA 濕度感應器的程式庫是針對 CircuitPython 所撰寫。若要在 Raspberry Pi 上執行它們，您需要安裝最新版本的 Python 3。

1. 從命令提示執行下列命令，以更新您的 Raspberry Pi 軟體：

   `sudo apt-get update`

   `sudo apt-get upgrade`

1. 執行以下命令來更新您的 Python 3 安裝：

   `sudo pip3 install --upgrade setuptools`

1. 執行以下命令來安裝 Raspberry Pi GPIO 程式庫：

   `pip3 install RPI.GPIO`

1. 執行以下命令來安裝 Adafruit Blinka 程式庫：

   `pip3 install adafruit-blinka`

   如需詳細資訊，請參閱 [在 Raspberry Pi 上安裝 CircuitPython 程式庫](https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi)。

1. 執行以下命令來安裝 Adafruit Seesaw 程式庫：

   `sudo pip3 install adafruit-circuitpython-seesaw`

1. 執行下列命令來安裝適用於 Python 的 AWS IoT 裝置 SDK：

   `pip3 install AWSIoTPythonSDK`

您的 Raspberry Pi 現在擁有所有必要的程式庫。建立名為 **moistureSensor.py** 的檔案，並將下列 Python 程式碼複製到檔案：

```
from adafruit_seesaw.seesaw import Seesaw
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient
from board import SCL, SDA

import logging
import time
import json
import argparse
import busio

# Shadow JSON schema:
#
# {
#   "state": {
#       "desired":{
#           "moisture":<INT VALUE>,
#           "temp":<INT VALUE>            
#       }
#   }
# }

# Function called when a shadow is updated
def customShadowCallback_Update(payload, responseStatus, token):

    # Display status and data from update request
    if responseStatus == "timeout":
        print("Update request " + token + " time out!")

    if responseStatus == "accepted":
        payloadDict = json.loads(payload)
        print("~~~~~~~~~~~~~~~~~~~~~~~")
        print("Update request with token: " + token + " accepted!")
        print("moisture: " + str(payloadDict["state"]["reported"]["moisture"]))
        print("temperature: " + str(payloadDict["state"]["reported"]["temp"]))
        print("~~~~~~~~~~~~~~~~~~~~~~~\n\n")

    if responseStatus == "rejected":
        print("Update request " + token + " rejected!")

# Function called when a shadow is deleted
def customShadowCallback_Delete(payload, responseStatus, token):

     # Display status and data from delete request
    if responseStatus == "timeout":
        print("Delete request " + token + " time out!")

    if responseStatus == "accepted":
        print("~~~~~~~~~~~~~~~~~~~~~~~")
        print("Delete request with token: " + token + " accepted!")
        print("~~~~~~~~~~~~~~~~~~~~~~~\n\n")

    if responseStatus == "rejected":
        print("Delete request " + token + " rejected!")


# Read in command-line parameters
def parseArgs():

    parser = argparse.ArgumentParser()
    parser.add_argument("-e", "--endpoint", action="store", required=True, dest="host", help="Your device data endpoint")
    parser.add_argument("-r", "--rootCA", action="store", required=True, dest="rootCAPath", help="Root CA file path")
    parser.add_argument("-c", "--cert", action="store", dest="certificatePath", help="Certificate file path")
    parser.add_argument("-k", "--key", action="store", dest="privateKeyPath", help="Private key file path")
    parser.add_argument("-p", "--port", action="store", dest="port", type=int, help="Port number override")
    parser.add_argument("-n", "--thingName", action="store", dest="thingName", default="Bot", help="Targeted thing name")
    parser.add_argument("-id", "--clientId", action="store", dest="clientId", default="basicShadowUpdater", help="Targeted client id")

    args = parser.parse_args()
    return args


# Configure logging
# AWSIoTMQTTShadowClient writes data to the log
def configureLogging():

    logger = logging.getLogger("AWSIoTPythonSDK.core")
    logger.setLevel(logging.DEBUG)
    streamHandler = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    streamHandler.setFormatter(formatter)
    logger.addHandler(streamHandler)


# Parse command line arguments
args = parseArgs()

if not args.certificatePath or not args.privateKeyPath:
    parser.error("Missing credentials for authentication.")
    exit(2)

# If no --port argument is passed, default to 8883
if not args.port: 
    args.port = 8883


# Init AWSIoTMQTTShadowClient
myAWSIoTMQTTShadowClient = None
myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient(args.clientId)
myAWSIoTMQTTShadowClient.configureEndpoint(args.host, args.port)
myAWSIoTMQTTShadowClient.configureCredentials(args.rootCAPath, args.privateKeyPath, args.certificatePath)

# AWSIoTMQTTShadowClient connection configuration
myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10) # 10 sec
myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(5) # 5 sec

# Initialize Raspberry Pi's I2C interface
i2c_bus = busio.I2C(SCL, SDA)

# Intialize SeeSaw, Adafruit's Circuit Python library
ss = Seesaw(i2c_bus, addr=0x36)

# Connect to AWS IoT
myAWSIoTMQTTShadowClient.connect()

# Create a device shadow handler, use this to update and delete shadow document
deviceShadowHandler = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(args.thingName, True)

# Delete current shadow JSON doc
deviceShadowHandler.shadowDelete(customShadowCallback_Delete, 5)

# Read data from moisture sensor and update shadow
while True:

    # read moisture level through capacitive touch pad
    moistureLevel = ss.moisture_read()

    # read temperature from the temperature sensor
    temp = ss.get_temp()

    # Display moisture and temp readings
    print("Moisture Level: {}".format(moistureLevel))
    print("Temperature: {}".format(temp))
    
    # Create message payload
    payload = {"state":{"reported":{"moisture":str(moistureLevel),"temp":str(temp)}}}

    # Update shadow
    deviceShadowHandler.shadowUpdate(json.dumps(payload), customShadowCallback_Update, 5)
    time.sleep(1)
```

將檔案儲存到您可以找到的位置。從命令列搭配下列參數執行 `moistureSensor.py`：

端點  
您的自訂 AWS IoT 端點。如需詳細資訊，請參閱[Device Shadow REST API](device-shadow-rest-api.md)。

rootCA  
 AWS IoT 根 CA 憑證的完整路徑。

cert  
裝置 AWS IoT 憑證的完整路徑。

金鑰  
裝置 AWS IoT 憑證私有金鑰的完整路徑。

thingName  
您的物件名稱 (在此案例中為 `RaspberryPi`)。

clientId  
MQTT 用戶端 ID。請使用 `RaspberryPi`。

命令列看起來應該如下：

`python3 moistureSensor.py --endpoint your-endpoint --rootCA ~/certs/AmazonRootCA1.pem --cert ~/certs/raspberrypi-certificate.pem.crt --key ~/certs/raspberrypi-private.pem.key --thingName RaspberryPi --clientId RaspberryPi`

嘗試碰觸感應器、將其放入花盆中，或將其放入杯水中，以查看感應器如何回應各種濕度。如有需要，您可以在 `MoistureSensorRule` 中變更閾值。當濕度感應器讀數低於規則 SQL 查詢陳述式中指定的值時， 會將訊息 AWS IoT 發佈至 Amazon SNS 主題。您應該會收到包含濕度和溫度資料的電子郵件訊息。

在您驗證收到來自 Amazon SNS 的電子郵件訊息後，請按 **CTRL\$1C** 來停止 Python 程式。Python 程式傳送的訊息量不足以產生費用，但最佳實務是在完成時停止程式。