

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

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