

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

# MQTT
<a name="device-advisor-tests-mqtt"></a>

## CONNECT、DISCONNECT 和 RECONNECT
<a name="connect"></a>

**「裝置將 CONNECT 傳送至 AWS IoT Core (Happy case)」**  <a name="MQTT_Connect"></a>
驗證測試下的裝置是否傳送 CONNECT 請求。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 2 分鐘。

```
"tests":[
   {
      "name":"my_mqtt_connect_test",
      "configuration": {
         // optional:
         "EXECUTION_TIMEOUT":"300",   // in seconds
      },
      "test":{
         "id":"MQTT_Connect",
         "version":"0.0.0"
      }
   }
]
```

**「裝置可將 PUBACK 傳回到 QOS1 的任意主題」**  
此測試案例將檢查裝置 （用戶端） 在訂閱 QoS1 主題之後，如果收到來自代理程式的發佈訊息，是否可以傳回 PUBACK 訊息。  
此測試案例的承載內容和承載大小是可設定的。如果已設定承載大小，Device Advisor 會覆寫承載內容的值，並將預先定義的承載傳送至具有所需大小的裝置。承載大小是介於 0 到 128 之間的值，且不能超過 128 KB。 AWS IoT Core 會拒絕發佈和連接大於 128 KB 的請求，如 [AWS IoT Core 訊息代理程式和通訊協定限制和配額](https://docs.aws.amazon.com/general/latest/gr/iot-core.html#message-broker-limits)頁面所示。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 2 分鐘。`PAYLOAD_SIZE` 可以設定為介於 0 到 128 KB 之間的值。定義承載大小會覆寫承載內容，因為 Device Advisor 會將具有指定大小的預先定義承載傳送回裝置。

```
"tests":[                            
{
        "name":"my_mqtt_client_puback_qos1",
        "configuration": {
            // optional:"TRIGGER_TOPIC": "myTopic",
            "EXECUTION_TIMEOUT":"300", // in seconds
            "PAYLOAD_FOR_PUBLISH_VALIDATION":"custom payload",
            "PAYLOAD_SIZE":"100" // in kilobytes
        },
        "test": {
            "id": "MQTT_Client_Puback_QoS1",
            "version": "0.0.0"
        }
    }
]
```

**「裝置在抖動退避的情況下重試連接：沒有 CONNACK 回應」**  <a name="MQTT_ConnectJitterBackoff"></a>
驗證測試下的裝置在與代理程式重新連線至少五次時，是否使用適當的抖動退避。代理程式記錄測試下裝置的 CONNECT 請求的時間戳記、執行封包驗證、暫停而不傳送 CONNACK 到測試下的裝置，以及等待測試下的裝置重新傳送請求。允許第六次連線嘗試通過，並允許 CONNACK 回流到測試下的裝置。  
再次執行上述程序。此測試案例需要裝置總共連接至少 12 次。收集的時間戳記用來驗證測試下的裝置是否使用抖動退避。如果待測裝置具有嚴格的指數退避延遲，則此測試案例會通過但有警告。  
建議對待測裝置實作[指數退避和抖動](https://aws.amazon.com/blogs//architecture/exponential-backoff-and-jitter/)機制，以通過此測試案例。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 4 分鐘。

```
"tests":[
   {
      "name":"my_mqtt_jitter_backoff_retries_test",
      "configuration": {
         // optional:
         "EXECUTION_TIMEOUT":"300",    // in seconds
      },
      "test":{
         "id":"MQTT_Connect_Jitter_Backoff_Retries",
         "version":"0.0.0"
      }
   }
]
```

**「裝置在指數退避的情況下重試連接：沒有 CONNACK 回應」**  
驗證測試下的裝置在與代理程式重新連線至少五次時，是否使用適當的指數退避。代理程式記錄測試下裝置的 CONNECT 請求的時間戳記、執行封包驗證、暫停而不傳送 CONNACK 到用戶端裝置，以及等待測試下的裝置重新傳送請求。收集的時間戳記用來驗證待測裝置是否使用指數退避。  
建議對待測裝置實作[指數退避和抖動](https://aws.amazon.com/blogs//architecture/exponential-backoff-and-jitter/)機制，以通過此測試案例。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 4 分鐘。

```
"tests":[
   {
      "name":"my_mqtt_exponential_backoff_retries_test",
      "configuration": {
         // optional:
         "EXECUTION_TIMEOUT":"600",  // in seconds
      },
      "test":{
         "id":"MQTT_Connect_Exponential_Backoff_Retries",
         "version":"0.0.0"
      }
   }
]
```

**「裝置在抖動退避的情況下重新連線：在伺服器中斷連線後」**  
驗證待測裝置在與伺服器中斷連線後重新連接時，是否使用必要的抖動和退避。Device Advisor 將裝置與伺服器的連線中斷至少五次，並觀察裝置在 MQTT 重新連線時的行為。Device Advisor 記錄待測裝置的 CONNECT 請求的時間戳記、執行封包驗證、暫停而不將 CONNACK 傳送到用戶端裝置，以及等待待測裝置重新傳送請求。收集的時間戳記用來驗證在重新連接時，待測裝置是否使用抖動和退避。如果待測裝置具有嚴格的指數退避，或未實作適當的抖動退避機制，則此測試案例會通過但有警告。如果待測裝置已實作線性退避或常數退避機制，則測試會失敗。  
若要通過這個測試案例，建議對待測裝置實作[指數退避和抖動](https://aws.amazon.com/blogs//architecture/exponential-backoff-and-jitter/)機制。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 4 分鐘。  
可以透過指定 `RECONNECTION_ATTEMPTS` 來變更驗證退避的重新連線嘗試次數。號碼必須為介於 5 到 10 之間的數字。預設值為 5。

```
"tests":[
   {
      "name":"my_mqtt_reconnect_backoff_retries_on_server_disconnect",
      "configuration":{
         // optional:
         "EXECUTION_TIMEOUT":"300",  // in seconds
         "RECONNECTION_ATTEMPTS": 5
      },
      "test":{
         "id":"MQTT_Reconnect_Backoff_Retries_On_Server_Disconnect",
         "version":"0.0.0"
      }
   }
]
```

**「裝置在抖動退避的情況下重新連線 - 連線不穩定」**  
驗證待測裝置在連線不穩定時，是否使用必要的抖動和退避。Device Advisor 會在 5 次成功連線後中斷裝置與伺服器的連線，並觀察裝置在 MQTT 重新連線時的行為。Device Advisor 會記錄待測裝置的 CONNECT 請求的時間戳記、執行封包驗證、傳送回 CONNACK、中斷連線、記錄中斷連線的時間戳記，以及等待待測裝置重新傳送請求。收集的時間戳記用來驗證在成功但不穩定的連線後重新連線時，待測裝置是否使用抖動和退避。如果待測裝置具有嚴格的指數退避，或未實作適當的抖動退避機制，則此測試案例會通過但有警告。如果待測裝置已實作線性退避或常數退避機制，則測試會失敗。  
若要通過這個測試案例，建議對待測裝置實作[指數退避和抖動](https://aws.amazon.com/blogs//architecture/exponential-backoff-and-jitter/)機制。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 4 分鐘。  
可以透過指定 `RECONNECTION_ATTEMPTS` 來變更驗證退避的重新連線嘗試次數。號碼必須為介於 5 到 10 之間的數字。預設值為 5。

```
"tests":[
   {
      "name":"my_mqtt_reconnect_backoff_retries_on_unstable_connection",
      "configuration":{
         // optional:
         "EXECUTION_TIMEOUT":"300",  // in seconds
         "RECONNECTION_ATTEMPTS": 5
      },
      "test":{
         "id":"MQTT_Reconnect_Backoff_Retries_On_Unstable_Connection",
         "version":"0.0.0"
      }
   }
]
```

## 發布
<a name="publish"></a>

**「QOS0 (Happy 案例)」**  <a name="MQTT_Publish"></a>
驗證測試中的裝置是否使用 QoS0 或 QoS1 發佈訊息。您也可以在測試設定中設定主題值和承載，來驗證訊息和承載的主題。  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 2 分鐘。

```
"tests":[
   {
      "name":"my_mqtt_publish_test",
      "configuration":{
         // optional:
         "EXECUTION_TIMEOUT":"300",  // in seconds
         "TOPIC_FOR_PUBLISH_VALIDATION": "my_TOPIC_FOR_PUBLISH_VALIDATION",
         "PAYLOAD_FOR_PUBLISH_VALIDATION": "my_PAYLOAD_FOR_PUBLISH_VALIDATION",
      },
      "test":{
         "id":"MQTT_Publish",
         "version":"0.0.0"
      }
   }
]
```

**「QOS1 發佈重試：沒有 PUBACK」**  
驗證若代理程式未傳送 PUBACK，測試下的裝置是否重新發佈與 QOS1 一起傳送的訊息。您也可以在測試設定中指定此主題，來驗證訊息的主題。用戶端裝置在重新發佈訊息之前不得中斷連線。此測試也會驗證重新發佈的訊息是否具有與原始訊息相同的封包識別符。測試執行期間，如果裝置失去連線並重新連接，則測試案例將重置而不會故障，並且裝置必須再次執行測試案例步驟。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。建議至少 4 分鐘。

```
"tests":[
   {
      "name":"my_mqtt_publish_retry_test",
      "configuration":{
         // optional:
         "EXECUTION_TIMEOUT":"300",  // in seconds
         "TOPIC_FOR_PUBLISH_VALIDATION": "my_TOPIC_FOR_PUBLISH_VALIDATION",
         "PAYLOAD_FOR_PUBLISH_VALIDATION": "my_PAYLOAD_FOR_PUBLISH_VALIDATION",
      },
      "test":{
         "id":"MQTT_Publish_Retry_No_Puback",
         "version":"0.0.0"
      }
   }
]
```

**「發佈保留的訊息」**  
驗證受測裝置是否會發佈 `retainFlag` 設定為 true 的訊息。您可以在測試設定中設定主題值和承載，來驗證訊息和承載的主題。如果在 PUBLISH 封包中傳送的 `retainFlag` 未設定為 true，測試案例將會失敗。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 2 分鐘。若要執行此測試案例，請在 [device role](https://docs.aws.amazon.com/iot/latest/developerguide/device-advisor-setting-up.html#da-iam-role) (裝置角色) 中新增 `iot:RetainPublish` 動作。

```
"tests":[
   {
      "name":"my_mqtt_publish_retained_messages_test",
      "configuration":{
         // optional:
         "EXECUTION_TIMEOUT":"300",  // in seconds
         "TOPIC_FOR_PUBLISH_RETAINED_VALIDATION": "my_TOPIC_FOR_PUBLISH_RETAINED_VALIDATION",
         "PAYLOAD_FOR_PUBLISH_RETAINED_VALIDATION": "my_PAYLOAD_FOR_PUBLISH_RETAINED_VALIDATION",
      },
      "test":{
         "id":"MQTT_Publish_Retained_Messages",
         "version":"0.0.0"
      }
   }
]
```

**「以使用者屬性進行發佈」**  
驗證受測裝置是否發佈含有正確使用者屬性的訊息。您可以在測試設定中設定名稱/值對來驗證使用者屬性。如果未提供使用者屬性或不相符，測試案例將會失敗。  
*API 測試案例定義：*  
這是僅限 MQTT5 的測試案例。  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 2 分鐘。

```
"tests":[
   {
      "name":"my_mqtt_user_property_test",
      "test":{
        "USER_PROPERTIES": [
            {"name": "name1", "value":"value1"},
            {"name": "name2", "value":"value2"}
        ],
        "EXECUTION_TIMEOUT":"300",  // in seconds
      },
      "test":{
         "id":"MQTT_Publish_User_Property",
         "version":"0.0.0"
      }
   }
]
```

## 訂閱
<a name="subscribe"></a>

**「可以訂閱 (Happy 案例)」**  <a name="MQTT_Subscribe"></a>
驗證測試下的裝置是否訂閱 MQTT 主題。您也可以在測試設定中指定此主題，來驗證測試下裝置所訂閱的主題。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 2 分鐘。

```
"tests":[
   {
      "name":"my_mqtt_subscribe_test",
      "configuration":{
         // optional:
         "EXECUTION_TIMEOUT":"300",  // in seconds
         "TOPIC_LIST_FOR_SUBSCRIPTION_VALIDATION":["my_TOPIC_FOR_PUBLISH_VALIDATION_a","my_TOPIC_FOR_PUBLISH_VALIDATION_b"]
      },
      "test":{
         "id":"MQTT_Subscribe",
         "version":"0.0.0"
      }
   }
]
```

**「訂閱重試：沒有 SUBACK」**  
驗證測試下的裝置是否重試失敗的 MQTT 主題訂閱。伺服器接著會等待，而且不會傳送 SUBACK。如果用戶端裝置沒有重試訂閱，測試會失敗。用戶端裝置必須使用相同的封包 ID 重試失敗的訂閱。您也可以在測試設定中指定此主題，來驗證測試下裝置所訂閱的主題。測試執行期間，如果裝置失去連線並重新連接，則測試案例將重置而不會故障，並且裝置必須再次執行測試案例步驟。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為 4 分鐘。

```
"tests":[
   {
      "name":"my_mqtt_subscribe_retry_test",
      "configuration":{
         "EXECUTION_TIMEOUT":"300",  // in seconds
         // optional:
         "TOPIC_LIST_FOR_SUBSCRIPTION_VALIDATION":["myTOPIC_FOR_PUBLISH_VALIDATION_a","my_TOPIC_FOR_PUBLISH_VALIDATION_b"]
      },
      "test":{
         "id":"MQTT_Subscribe_Retry_No_Suback",
         "version":"0.0.0"
      }
   }
]
```

## Keep-Alive
<a name="keep-alive"></a>

**「Mqtt No Ack PingResp」**  
這個測試案例會驗證，如果待測裝置在未收到 Ping 回應時是否會中斷連線。在此測試案例中，Device Advisor 會封鎖從 傳送的回應， AWS IoT Core 以進行發佈、訂閱和 ping 請求。其也會驗證待測裝置是否中斷與 MQTT 的連線。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。建議使用的逾時值大於 `keepAliveTime` 值的 1.5 倍。  
 此測試的最大值`keepAliveTime`不得超過 230 秒。

```
"tests":[
    {
       "name":"Mqtt No Ack PingResp",
       "configuration": 
          //optional:
          "EXECUTION_TIMEOUT":"306",   // in seconds
       },
       "test":{
          "id":"MQTT_No_Ack_PingResp",
          "version":"0.0.0"
       }
    }
]
```

## 持久性工作階段
<a name="persistent-session"></a>

**「持久性階段作業 (Happy 案例)」**  
此測試案例會驗證裝置與持久性階段作業中斷連結時的行為。此測試案例會檢查裝置是否可以重新連接、恢復其觸發程序主題訂閱而不需明確重新訂閱、接收儲存於主題中的訊息，以及在持久性階段作業期間如預期運作。當此測試案例通過時，表示用戶端裝置能夠以預期的方式與 AWS IoT Core 代理程式維持持久性工作階段。如需 AWS IoT 持久性工作階段的詳細資訊，請參閱[使用 MQTT 持久性工作階段](https://docs.aws.amazon.com/iot/latest/developerguide/mqtt.html#mqtt-persistent-sessions)。  
在此測試案例中，用戶端裝置應在乾淨的階段作業旗標設為 false 下與 AWS IoT Core 連結，並且訂閱主題篩選條件。成功訂閱後，裝置將由 AWS IoT Core Device Advisor 中斷連線。當裝置處於中斷連結的狀態時，QoS 1 訊息承載將儲存在該主題中。Device Advisor 將允許用戶端裝置與測試端點重新連結。此時由於有持久性工作階段，用戶端裝置應恢復其主題訂閱，而不需傳送任何額外的訂閱封包，並從代理程式接收 QoS 1 訊息。重新連結後，如果用戶端裝置傳送額外的 SUBSCRIBE 封包，再次重新訂閱其觸發程序主題，和/或如果用戶端並未收到來自觸發程序主題的儲存訊息，測試案例將會失敗。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為至少 4 分鐘。第一次連線時，用戶端裝置需要明確訂閱之前沒有訂閱的 `TRIGGER_TOPIC`。若要通過測試案例，用戶端裝置必須使用 QoS 1 成功訂閱 `TRIGGER_TOPIC`。重新連結後，用戶端裝置應了解有作用中的持久性工作階段；因此應接受觸發程序主題傳送的已儲存訊息，並針對該特定訊息傳回 PUBACK。

```
"tests":[
   {
      "name":"my_mqtt_persistent_session_happy_case",
      "configuration":{
         //required:
         "TRIGGER_TOPIC": "myTrigger/topic",
         // optional:
         // if Payload not provided, a string will be stored in the trigger topic to be sent back to the client device
         "PAYLOAD": "The message which should be received from AWS IoT Broker after re-connecting to a persistent session from the specified trigger topic.",            
         "EXECUTION_TIMEOUT":"300" // in seconds
      },
      "test":{
         "id":"MQTT_Persistent_Session_Happy_Case",
         "version":"0.0.0"
      }
   }
]
```

**「持久性工作階段到期 - 工作階段到期」**  
此測試案例有助於在已中斷連線的裝置重新連線到過期的持久性工作階段時，驗證裝置行為。工作階段過期後，我們希望裝置透過明確傳送新的 SUBSCRIBE 封包來重新訂閱之前訂閱的主題。  
在第一次連線期間，我們預期測試裝置會與 AWS IoT 代理程式連線，因為其`CleanSession`旗標設為 false 以啟動持久性工作階段。然後，裝置應訂閱觸發程序主題。然後，在成功訂閱和啟動持久性工作階段後， AWS IoT Core Device Advisor 會中斷裝置連線。中斷連線後， AWS IoT Core Device Advisor 會允許測試裝置重新連線至測試端點。此時，當測試裝置傳送另一個 CONNECT 封包時， AWS IoT Core Device Advisor 會傳回 CONNACK 封包，指出持久性工作階段已過期。測試裝置需要正確解譯此封包，並且在持久性工作階段終止時，應再次重新訂閱相同的觸發程序主題。如果測試裝置未重新訂閱其主題觸發程序，則測試案例失敗。為了通過測試，裝置需要了解持久性工作階段已經結束，並在第二次連線對同一個觸發程序主題回傳一個新的 SUBSCRIBE 封包。  
如果此測試案例對於某測試裝置通過，表示該裝置能在持久性工作階段過期時以預期的方式處理重新連線。  
*API 測試案例定義：*  
`EXECUTION_TIMEOUT` 的預設值為 5 分鐘。我們建議的逾時值為至少 4 分鐘。測試裝置需要明確訂閱之前沒有訂閱的 `TRIGGER_TOPIC`。要通過測試案例，測試裝置必須在 `CleanSession` 旗標設為 false 下傳送 CONNECT 封包，並成功訂閱具有 QoS 1 的觸發程序主題。成功連線後， AWS IoT Core Device Advisor 會中斷裝置連線。中斷連線後， AWS IoT Core Device Advisor 允許裝置重新連線，且裝置預期會重新訂閱相同的 ，`TRIGGER_TOPIC`因為 AWS IoT Core Device Advisor 會終止持久性工作階段。

```
"tests":[
   {
      "name":"my_expired_persistent_session_test",
      "configuration":{
         //required:
         "TRIGGER_TOPIC": "myTrigger/topic",
         // optional:       
         "EXECUTION_TIMEOUT":"300" // in seconds
      },
      "test":{
         "id":"MQTT_Expired_Persistent_Session",
         "version":"0.0.0"
      }
   }
]
```