

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

# 使用二進位承載
<a name="binary-payloads"></a>

若要將訊息承載做為原始二進位資料 (而不是 JSON 物件) 處理，可以使用 \$1 運算子在 SELECT 子句中參考它。

**Topics**
+ [二進位承載範例](#binary-payloads-examples)
+ [對 Protobuf 訊息承載進行解碼](#binary-payloads-protobuf)

## 二進位承載範例
<a name="binary-payloads-examples"></a>

使用 \$1 參考作為原始二進位資料的訊息承載時，您可以將資料新增至規則。如果您有空白或 JSON 承載，則產生的承載可以使用規則新增資料。下列顯示支援 `SELECT` 子句的範例。
+ 對於二進位承載，您可以使用下方僅具有一個 \$1 的 `SELECT` 子句。
  + 

    ```
    SELECT * FROM 'topic/subtopic'
    ```
  + 

    ```
    SELECT * FROM 'topic/subtopic' WHERE timestamp() % 12 = 0
    ```
+ 您也可以新增資料並使用下方 `SELECT` 子句。
  + 

    ```
    SELECT *, principal() as principal, timestamp() as time FROM 'topic/subtopic'
    ```
  + 

    ```
    SELECT encode(*, 'base64') AS data, timestamp() AS ts FROM 'topic/subtopic'
    ```
+ 您也可以使用這些 `SELECT` 子句搭配二進位承載使用。
  + 下方項目是指 WHERE 子句中的 `device_type`。

    ```
    SELECT * FROM 'topic/subtopic' WHERE device_type = 'thermostat'
    ```
  + 也支援下方項目。

    ```
    {
    	"sql": "SELECT * FROM 'topic/subtopic'",
    	"actions": [
    		{
    			"republish": {
    				"topic": "device/${device_id}"
    			}
    		}
    	]
    }
    ```

下方規則動作不支援二進位承載，因此您必須將它們解碼。
+ 對於某些不支援二進位承載輸入 (例如 [Lambda 動作](https://docs.aws.amazon.com/iot/latest/developerguide/iot-rule-actions.html#lambda-rule)) 的規則，您必須解碼二進位承載。如果 Lambda 規則動作是 base64 編碼且在 JSON 承載中，則可以接收二進位資料。您可以將規則變更如下，以此執行此項操作。

  ```
  SELECT encode(*, 'base64') AS data FROM 'my_topic'
  ```
+ SQL 陳述式不支援將字串作為輸入。若要將字串輸入轉換為 JSON，您可以執行下列命令。

  ```
  SELECT decode(encode(*, 'base64'), 'base64') AS payload FROM 'topic'
  ```

## 對 Protobuf 訊息承載進行解碼
<a name="binary-payloads-protobuf"></a>

[協定緩衝區（protobuf）](https://developers.google.com/protocol-buffers)是一種開放原始碼資料格式，用於將結構化資料序列化為壓縮二進位形式。其可用於透過網路傳輸資料或將其儲存在檔案中。Protobuf 可讓您以小封包大小並以比其他簡訊格式更快的速度傳送資料。 AWS IoT Core Rules 支援 protobuf，方法是提供 [decode(value， decodingScheme)](iot-sql-functions.md#iot-sql-decode-base64) SQL 函數，這可讓您將 protobuf 編碼的訊息承載解碼為 JSON 格式，並將其路由至下游服務。本節詳細介紹在 AWS IoT Core 規則中設定 protobuf 解碼的逐步流程。

**Topics**
+ [先決條件](#binary-payloads-protobuf-prerequisites)
+ [建立描述項檔案](#binary-payloads-protobuf-descriptor-steps)
+ [將描述項檔案上傳至 S3 儲存貯體](#binary-payloads-protobuf-s3-steps)
+ [在規則中設定 protobuf 解碼](#binary-payloads-protobuf-steps)
+ [限制](#binary-payloads-protobuf-limitations)
+ [最佳實務](#binary-payloads-protobuf-bestpractices)

### 先決條件
<a name="binary-payloads-protobuf-prerequisites"></a>
+ [協定緩衝區 (protobuf)](https://developers.google.com/protocol-buffers) 的基本知識
+ 該[`.proto` 檔案](https://developers.google.com/protocol-buffers/docs/proto3)定義了訊息類型及相關的相依性
+ 在您的系統上安裝 [Protobuf 編譯器 (protoc)](https://github.com/protocolbuffers/protobuf/releases)

### 建立描述項檔案
<a name="binary-payloads-protobuf-descriptor-steps"></a>

如果您已有描述項檔案，則可以略過此步驟。描述項檔案 (`.desc`) 是 `.proto` 檔案的編譯版本，屬於文字檔案，用於定義在 protobuf 序列化中使用的資料結構和訊息類型。要產生描述項檔案，您必須定義 `.proto` 檔案並使用 [protoc](https://github.com/protocolbuffers/protobuf/releases) 編譯器對其進行編譯。

1. 建立用於定義訊息類型的 `.proto` 檔案。範例 `.proto` 檔案看起來可能與以下內容相似：

   ```
   syntax = "proto3";
   
   message Person {
     optional string name = 1;
     optional int32 id = 2;
     optional string email = 3;
   }
   ```

   在此範例 `.proto` 檔案中，您使用 proto3 語法並定義訊息類型 `Person`。`Person` 訊息定義會指定三個欄位 (名稱、ID 和電子郵件)。如需有關 `.proto` 檔案訊息格式的詳細資訊，請參閱 [語言指南 (proto3)](https://developers.google.com/protocol-buffers/docs/proto3)。

1. 使用 [protoc](https://github.com/protocolbuffers/protobuf/releases) 編譯器編譯 `.proto` 檔案並產生描述項檔案。用於建立描述項 (`.desc`) 檔案的範例命令如下所示：

   ```
   protoc --descriptor_set_out=<FILENAME>.desc \
       --proto_path=<PATH_TO_IMPORTS_DIRECTORY> \
       --include_imports \
       <PROTO_FILENAME>.proto
   ```

   此範例命令會產生描述項檔案 `<FILENAME>.desc`， AWS IoT Core 規則可用來解碼符合 中定義之資料結構的 protobuf 承載`<PROTO_FILENAME>.proto`。
   + `--descriptor_set_out`

     指定所要產生的描述項檔案 (`<FILENAME>.desc`) 名稱。
   + `--proto_path`

     指定編譯檔案所參考的任何已匯入 `.proto` 檔案的位置。如果您有多項已匯入的 `.proto` 檔案位於不同位置，則可以多次指定旗標。
   + `--include_imports`

     指定任何已匯入的 `.proto` 檔案也應加以編譯，並納入 `<FILENAME>.desc` 描述項檔案中。
   + `<PROTO_FILENAME>.proto`

     指定要編譯的 `.proto` 檔案名稱。

   如需 protoc 參考的詳細資訊，請參閱 [API 參考](https://developers.google.com/protocol-buffers/docs/reference/overview)。

### 將描述項檔案上傳至 S3 儲存貯體
<a name="binary-payloads-protobuf-s3-steps"></a>

建立描述項檔案 之後`<FILENAME>.desc`，請使用 AWS API、 AWS SDK 或 將描述項檔案上傳至 Amazon S3 `<FILENAME>.desc`儲存貯體 AWS 管理主控台。

**重要考量**
+ 請確定您上傳描述項檔案到 中 Amazon S3 儲存貯 AWS 帳戶 體的 ，與您打算設定規則 AWS 區域 的位置相同。
+ 請務必授予`FileDescriptorSet`從 S3 讀取 的 AWS IoT Core 存取權。如果 S3 儲存貯體已停用伺服器端的加密 (SSE)，或者 S3 儲存貯體是使用 Amazon S3 受管金鑰 (SSE-S3) 進行加密，則不需要其他政策組態。下列範例儲存貯體政策可實現此目的：  
****  

  ```
  {
  	"Version":"2012-10-17",		 	 	 
  	"Statement": [
  		{
  			"Sid": "Statement1",
  			"Effect": "Allow",
  			"Principal": {
  				"Service": "iot.amazonaws.com"
  			},
  			"Action": "s3:Get*",
                        "Resource": "arn:aws:s3:::<BUCKET NAME>/<FILENAME>.desc"
  		}
  	]
  }
  ```
+ 如果您的 S3 儲存貯體使用 AWS Key Management Service 金鑰 (SSE-KMS) 加密，請務必在存取 S3 儲存貯體時授予使用金鑰的 AWS IoT Core 許可。作法為您可以將下列陳述式新增至金鑰政策：

  ```
  {
  	"Sid": "Statement1",
  	"Effect": "Allow",
  	"Principal": {
  		"Service": "iot.amazonaws.com"
  	},
  	"Action": [
  		"kms:Decrypt",
  		"kms:GenerateDataKey*",
  		"kms:DescribeKey"
  	],
          "Resource": "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
  	
  }
  ```

### 在規則中設定 protobuf 解碼
<a name="binary-payloads-protobuf-steps"></a>

將描述項檔案上傳到 Amazon S3 儲存貯體後，請設定一項[規則](https://docs.aws.amazon.com//iot/latest/developerguide/iot-create-rule.html)以供使用 [decode(value, decodingScheme)](iot-sql-functions.md#iot-sql-decode-base64) SQL 函數來解碼 protobuf 訊息承載格式。詳細的函數簽章和範例可參見 *AWS IoT SQL 參考*的 [decode(value, decodingScheme)](iot-sql-functions.md#iot-sql-decode-base64) SQL 函數。

以下是使用 [decode(value, decodingScheme)](iot-sql-functions.md#iot-sql-decode-base64) 函數的 SQL 表達式範例：

```
SELECT VALUE decode(*, 'proto', '<BUCKET NAME>', '<FILENAME>.desc', '<PROTO_FILENAME>', '<PROTO_MESSAGE_TYPE>') FROM '<MY_TOPIC>'
```

在此範例表達式中：
+ 您可以使用 [decode(value, decodingScheme)](iot-sql-functions.md#iot-sql-decode-base64) SQL 函數，來解碼 `*` 參考的二進位訊息承載。這可以是二進位 protobuf 編碼承載，也可以是代表 base64 編碼 protobuf 承載的 JSON 字串。
+ 所提供的訊息承載會使用 `PROTO_FILENAME.proto` 中定義的`Person` 訊息類型進行編碼。
+ 名為 `BUCKET NAME` 的 Amazon S3 儲存貯體含有從 `PROTO_FILENAME.proto` 產生的 `FILENAME.desc`。

完成組態後，請在規則訂閱的主題 AWS IoT Core 上發佈訊息至 。

### 限制
<a name="binary-payloads-protobuf-limitations"></a>

AWS IoT Core 規則支援具有下列限制的 protobuf：
+ 不支援在[替代範本](https://docs.aws.amazon.com//iot/latest/developerguide/iot-substitution-templates.html)中解碼 protobuf 訊息承載。
+ 在解碼 protobuf 訊息承載時，您最多可以在單一 SQL 表達式中使用[解碼 SQL 函數](iot-sql-functions.md#iot-sql-decode-base64) 2 次。
+ 傳入承載大小上限為 128 KiB (1KiB = 1024 位元組)，傳出承載大小上限為 128 KiB，而儲存在 Amazon S3 儲存貯體中的 `FileDescriptorSet` 物件大小上限為 32 KiB。
+ 不支援使用 SSE-C 加密功能對 Amazon S3 儲存貯體進行加密。

### 最佳實務
<a name="binary-payloads-protobuf-bestpractices"></a>

以下是一些最佳實務和疑難排解提示。
+ 在 Amazon S3 儲存貯體中備份原型檔案。

  理想的做法是備份 proto 檔案以防患未然。例如，如果在執行 protoc 時錯誤地修改了沒有備份的原型檔案，這可能會導致生產堆疊發生問題。有多種方法在 Amazon S3 儲存貯體中備份檔案 例如，您可以[在 S3 儲存貯體中使用版本控制](https://docs.aws.amazon.com//AmazonS3/latest/userguide/Versioning.html)。如需有關如何備份 Amazon S3 儲存貯體中檔案的詳細資訊，請參閱 *[Amazon S3 開發人員指南](https://docs.aws.amazon.com//aws-backup/latest/devguide/recovery-points.html)*。
+ 設定 AWS IoT 記錄以檢視日誌項目。

  設定 AWS IoT 記錄是很好的做法，讓您可以在 CloudWatch 中檢查帳戶的 AWS IoT 日誌。當規則的 SQL 查詢呼叫外部 函數時， AWS IoT Core Rules 會產生具有 之 `eventType`的日誌項目`FunctionExecution`，其中包含可協助您對失敗進行疑難排解的原因欄位。可能的錯誤包括找不到 Amazon S3 物件，或是 protobuf 檔案描述項無效。如需進一步了解如何設定 AWS IoT 記錄及查看日誌項目，請參閱[設定 AWS IoT 記錄](https://docs.aws.amazon.com//iot/latest/developerguide/configure-logging.html)和[規則引擎日誌項目](https://docs.aws.amazon.com//iot/latest/developerguide/cwl-format.html#log-rules-fn-exec)。
+ 使用新的物件索引鍵來更新 `FileDescriptorSet` 以及更新規則中的物件索引鍵。

  您可以將更新後的描述項檔案上傳到 Amazon S3 儲存貯體來更新 `FileDescriptorSet`。系統可能需要最多 15 分鐘的時間來反映 `FileDescriptorSet` 的更新作業。為了避免這種延遲，理想做法是使用新的物件索引鍵上傳更新後的 `FileDescriptorSet`，並在規則中更新物件索引鍵。