

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 教程：使用设备 SDK 将 AWS IoT 设备连接到 AWS IoT Core
<a name="sdk-tutorials"></a>

本教程演示了如何将设备连接起来， AWS IoT Core 以便它可以向和从设备发送和接收数据 AWS IoT。完成本教程后，您的设备将被配置为连接，您将了解设备是如何与之通信的 AWS IoT。 AWS IoT Core 

**Topics**
+ [先决条件](#sdk-tutorials-prereq)
+ [为设备做好准备 AWS IoT](#sdk-tutorials-prepare)
+ [查看 MQTT 协议](#sdk-tutorials-mqtt-review)
+ [查看 pubsub.py Device SDK 示例应用程序](#sdk-tutorials-explore-sample)
+ [连接您的设备并与之通信 AWS IoT Core](#sdk-tutorials-experiment)
+ [查看结果](#sdk-tutorials-conclusion)
+ [教程：使用 AWS IoT Device SDK for Embedded C](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 设备 SDK v2 的设备。**  
本教程介绍如何使用 Python 代码示例将设备连接到 AWS IoT Core 设备，这需要相对强大的设备。如果您使用的是资源受限的设备，则这些代码示例可能无法适用于这些设备。在这种情况下，使用 [教程：使用 AWS IoT Device SDK for Embedded C](iot-embedded-c-sdk.md) 教程可能会更成功。
+ 

**获取连接到设备所需的信息**  
要将设备连接到 AWS IoT，您必须拥有有关事物名称、主机名和端口号的信息。
**注意**  
您也可以使用自定义身份验证将设备连接到 AWS IoT Core。您传递给授权方 Lambda 函数的连接数据取决于您使用的协议。
  + **事物名称**：您要连接 AWS IoT 的事物的名称。你一定已经注册为你的设备 AWS IoT 了。有关更多信息，请参阅 [使用管理设备 AWS IoT](iot-thing-management.md)。
  + **主机名**：特定于账户的物联网端点的主机名。
  + **端口号**：要连接到的端口号。

  您可以使用 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 账户](setting-up.md)介绍了如何创建一个（ AWS 账户 如果您还没有）。

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 设备之类的@@ **通信软件** SDKs 提供。本教程使用 [AWS IoT Device SDK v2 for Python](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 协议。与其它网络通信协议（如 HTTP）相比，MQTT 协议具有一些优势，这使得它成为了物联网设备的常用选择。本部分回顾的是适用于本教程的 MQTT 的主要方面。有关如何将 MQTT 与 HTTP 进行比较的信息，请参阅 [为设备通信选择应用程序协议](protocols.md#protocol-selection)。

**MQTT 使用 publish/subscribe 通信模型**  
MQTT 协议使用与其主机的 publish/subscribe 通信模型。此模型不同于 HTTP 使用的 request/response 模型。借助 MQTT，设备可以与由唯一客户端 ID 标识的主机建立会话。要发送数据，设备会将主题标识的消息发布到主机中的消息代理上。要接收来自消息代理的消息，设备通过在订阅请求中向消息代理发送主题筛选条件，来订阅主题。

**MQTT 支持持久会话**  
消息代理接收来自设备的消息，并将消息发布到已订阅消息的设备。借助[持久会话](mqtt.md#mqtt-persistent-sessions)（即使在初始设备断开连接时，仍能保持活动状态的会话），设备可以检索在断开连接时发布的消息。在设备端，MQTT 支持服务质量级别（[QoS](mqtt.md#mqtt-qos)），以确保主机接收设备发送的消息。

## 查看 pubsub.py Device SDK 示例应用程序
<a name="sdk-tutorials-explore-sample"></a>

本部分将回顾本教程中适用的来自 **AWS IoT Device SDK v2 for Python** 中的 `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 和 MQTT over WSS 协议进行的 MQTT 连接。[AWS 通用运行时 (AWS CRT)](https://github.com/awslabs/aws-crt-python#aws-crt-python) 库提供低级通信协议支持，包含在适用于 Python 的 AWS IoT 设备 SDK v2 中。

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

中的`pubsub.py`示例调用`mtls_from_path`（如图所示）使用 MQTT 协议与 AWS IoT Core 之建立连接。[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`使用 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 账户联网设备端点  
在示例应用程序中，此值将从命令行传入。

`cert_filepath`  
设备证书文件的路径。  
在示例应用程序中，此值将从命令行传入。

`pri_key_filepath`  
使用其证书文件创建的设备私有密钥文件的路径  
在示例应用程序中，此值将从命令行传入。

`ca_filepath`  
Root 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 V4](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 账户联网设备端点  
在示例应用程序中，此值将从命令行传入。

`client_bootstrap`  
处理套接字通信活动的通用运行时对象  
在示例应用程序中，此对象会在调用 `mqtt_connection_builder.websockets_with_default_aws_signing`前实例化。

`region`  
 AWS 签名 V4 身份验证使用的签名区域。在 `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`  
Root 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 QoS 级别**  

| MQTT QoS 级别 | SDK 使用的 Python 符号值 | 说明 | 
| --- | --- | --- | 
| 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)查看您的设备发布的内容，并将消息发布到您的设备。这些练习使用来自 [AWS IoT Device SDK v2 for Python](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_cn/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_cn/iot/latest/developerguide/sdk-tutorials.html)

1. 使用 AWS IoT 控制台中的 MQTT 测试客户端，将上一步中所述的消息发送到您的设备。

   1. 在 AWS IoT 控制台中打开 [MQTT 测试客户端](https://console.aws.amazon.com/iot/home#/test)。

   1. 在**订阅主题**中，在**订阅主题字段**输入主题筛选条件：**device/\$1/details**，然后选择**订阅主题**。

   1. 在 MQTT 测试客户端中的**订阅**列中，选择 **device/\$1/details**。

   1. 对于上表中的每个主题，请在 MQTT 测试客户端中执行以下操作：

      1. 在**发布**中，在表中输入**主题名称**列的值。

      1. 在主题名称下方的消息有效载荷字段中，在表中输入**消息有效载荷**列的值。

      1. 观看 `pubsub.py` 运行所在的终端窗口，并在 MQTT 测试客户端中选择**发布到主题**。

      您应该看到该消息是由终端窗口中的 `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. 在**订阅主题**中，在**订阅主题字段**输入主题筛选条件：**device/\$1/details**，然后选择**订阅主题**。

1. 在 MQTT 测试客户端中的 **Subscriptions**（订阅）列中，选择**device/\$1/details**。

1. 对于此表中的每个主题，请在 MQTT 测试客户端中执行以下操作：    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/iot/latest/developerguide/sdk-tutorials.html)

   1. 在 **Publish**（发布）中，在表中输入 **Topic name**（主题名称）列的值。

   1. 在主题名称下方的消息有效载荷字段中，在表中输入**消息有效载荷**列的值。

   1. 观看 `pubsub.py` 运行所在的终端窗口，并在 MQTT 测试客户端中选择**发布到主题**。

   您应该看到该消息是由终端窗口中的 `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 topic**（订阅主题）中，在 **Subscription topic field**（订阅主题字段）输入主题筛选条件：**device/data**，然后选择 **Subscribe to topic**（订阅主题）。

1. 在 **Subscriptions**（订阅）列中，选择 **device/data**（设备/数据）。

1. 将 MQTT 测试客户端窗口保持打开状态，等待来自设备的消息。

**使用 pubsub.py 示例应用程序发送 JSON 文档**

1. 在您的设备上，将 `pubsub.py` 复制到 `pubsub3.py`。

1. 编辑 `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_cn/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)

# 教程：使用 AWS IoT Device SDK for Embedded C
<a name="iot-embedded-c-sdk"></a>

此部分描述如何运行 AWS IoT Device SDK for Embedded C。

**Topics**
+ [步骤 1：安装 AWS IoT Device SDK for Embedded C](#install-embedded-c-sdk)
+ [步骤 2：配置示例应用](#iot-c-sdk-app-config)
+ [步骤 3：构建并运行示例应用程序](#iot-c-sdk-app-run)

## 步骤 1：安装 AWS IoT Device SDK for Embedded C
<a name="install-embedded-c-sdk"></a>

AWS IoT Device SDK for Embedded C通常面向需要优化的 C 语言运行时的资源受限设备。您可以在任何操作系统上使用此 SDK，并将其托管在任何类型的处理器（例如 MCU 和 MPU）上。如果您有更多的可用内存和处理资源，我们建议您使用更高级的 AWS IoT设备和移动 SDK 之一（例如，C\$1\$1、Java、JavaScript 和 Python）。

一般而言，AWS IoT Device SDK for Embedded C适用于以下系统：这些系统使用 MCU 或运行嵌入式操作系统的低端 MPU。对于本部分中的编程示例，我们假定您的设备使用 Linux。

**Example**  

1. 从 [GitHub](https://github.com/aws/aws-iot-device-sdk-embedded-C) 将 AWS IoT Device SDK for Embedded C下载到您的设备。

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

AWS IoT Device SDK for Embedded C 包含供您试用的示例应用程序。为了简单起见，本教程使用的是 `mqtt_demo_mutual_auth`应用程序，此应用程序演示如何连接到 AWS IoT Core消息代理并订阅和发布到 MQTT 主题。

1. 将您在 [AWS IoT Core 教程入门](iot-gs.md)中创建的证书和私有密钥复制到 `build/bin/certificates`目录中。
**注意**  
设备和根 CA 证书可能会过期或被吊销。如果您的证书过期或被吊销，则您必须将新的 CA 证书或私有密钥和设备证书复制到您的设备上。

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 Device SDK for Embedded C 将其连接到 [AWS IoT 控制台](https://console.aws.amazon.com/iot/home)。

**运行 AWS IoT Device SDK for Embedded C示例应用程序**

1. 导航到 `aws-iot-device-sdk-embedded-c`并创建目录。

   ```
   mkdir build && cd build
   ```

1. 输入以下 CMake 命令以生成 Makefiles 构建所需的文件。

   ```
   cmake ..  
   ```

1. 输入以下命令以构建可执行应用程序文件。

   ```
   make
   ```

1. 使用此命令运行 `mqtt_demo_mutual_auth`应用程序。

   ```
   cd bin
   ./mqtt_demo_mutual_auth
   ```

   您应该可以看到类似于如下所示的输出内容：  
![\[运行 AWS IoT Device SDK for Embedded C 示例应用程序的命令行输出。\]](http://docs.aws.amazon.com/zh_cn/iot/latest/developerguide/images/successful-run2.png)

设备现已使用 AWS IoT Device SDK for Embedded C连接到 AWS IoT。

您还可以使用 AWS IoT控制台查看示例应用程序正在发布的 MQTT 消息。有关如何在 [AWS IoT控制台](https://console.aws.amazon.com/iot/home)中使用 MQTT 客户端的信息，请参阅[使用 MQTT 客户端查看 AWS IoT MQTT 消息](view-mqtt-messages.md)。