

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

# 教學課程： 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)。