

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# アプリケーションへの OTA エージェントの統合
<a name="integrate-ota-agent"></a>

無線通信 (OTA) エージェントは、OTA 更新機能を製品に追加するために記述する必要があるコードの量を簡素化するように設計されています。この統合の負担は、主に OTA エージェントの初期化と、OTA エージェントイベントメッセージに応答するためのカスタムコールバック関数の作成です。OS の初期化中に、MQTT、HTTP (HTTP がファイルのダウンロードに使用されている場合)、およびプラットフォーム固有の実装 (PAL) インターフェイスが OTA エージェントに渡されます。バッファを初期化して OTA エージェントに渡すこともできます。

**注記**  
アプリケーションに OTA 更新機能を統合するのは簡単ですが、OTA の更新システムでは、単にデバイスコードの統合以上のことを理解する必要があります。モノ、認証情報、コード署名証明書、プロビジョニングデバイス、OTA 更新ジョブを使用して AWS AWS IoT アカウントを設定する方法を理解するには、[FreeRTOS の前提条件](https://docs.aws.amazon.com/freertos/latest/userguide/freertos-prereqs.html)」を参照してください。

## 接続管理
<a name="ota-agent-http-mqtt"></a>

OTA エージェントは、 AWS IoT サービスに関連するすべてのコントロール通信オペレーションに MQTT プロトコルを使用しますが、MQTT 接続は管理しません。OTA エージェントがアプリケーションの接続管理ポリシーを妨げないようにするには、切断と再接続機能を含む MQTT 接続をメインのユーザーアプリケーションで処理する必要があります。このファイルは MQTT または HTTP プロトコルでダウンロードできます。OTA ジョブを作成するときに、プロトコルを選択できます。MQTT を選択した場合、OTA エージェントは制御オペレーションとファイルのダウンロードに同じ接続を使用します。

## シンプルな OTA デモ
<a name="simple-demo-agent"></a>

以下は、エージェントが MQTT ブローカーに接続して OTA エージェントを初期化する方法を示すシンプルな OTA デモの抜粋です。この例ではデモ用に、デフォルトの OTA アプリケーションコールバックを使用し、1 秒ごとに統計情報をいくつか返す設定をします。簡潔にするために、このデモから一部の詳細を省略します。

OTA デモでは、切断コールバックをモニタリングし、接続を再確立する MQTT 接続管理も実演します。このデモでは、切断発生後に、まず OTA エージェントのオペレーションを中断し、次に MQTT 接続の再確立を試みます。MQTT 再接続試行までの時間間隔は、最大値まで指数関数的に増えていき、ジッターも追加されます。接続が再確立されると、OTA エージェントによるオペレーションが続行されます。

 AWS IoT MQTT ブローカーを使用する実例については、 `demos/ota` ディレクトリの OTA デモコードを参照してください。

OTA エージェントは独自のタスクなので、この例の意図的な 1 秒の遅れはこのアプリケーションにのみ影響します。エージェントのパフォーマンスに影響はありません。

```
static BaseType_t prvRunOTADemo( void )
{
    /* Status indicating a successful demo or not. */
    BaseType_t xStatus = pdFAIL;

    /* OTA library return status. */
    OtaErr_t xOtaError = OtaErrUninitialized;

    /* OTA event message used for sending event to OTA Agent.*/
    OtaEventMsg_t xEventMsg = { 0 };

    /* OTA interface context required for library interface functions.*/
    OtaInterfaces_t xOtaInterfaces;

    /* OTA library packet statistics per job.*/
    OtaAgentStatistics_t xOtaStatistics = { 0 };

    /* OTA Agent state returned from calling OTA_GetState.*/
    OtaState_t xOtaState = OtaAgentStateStopped;

    /* Set OTA Library interfaces.*/
    prvSetOtaInterfaces( &xOtaInterfaces );

    /*************************** Init OTA Library. ***************************/

    if( ( xOtaError = OTA_Init( &xOtaBuffer,
                                &xOtaInterfaces,
                                ( const uint8_t * ) ( democonfigCLIENT_IDENTIFIER ),
                                prvOtaAppCallback ) ) != OtaErrNone )
    {
        LogError( ( "Failed to initialize OTA Agent, exiting = %u.",
                    xOtaError ) );
    }
    else
    {
        xStatus = pdPASS;
    }

    /************************ Create OTA Agent Task. ************************/

    if( xStatus == pdPASS )
    {
        xStatus = xTaskCreate( prvOTAAgentTask,
                               "OTA Agent Task",
                               otaexampleAGENT_TASK_STACK_SIZE,
                               NULL,
                               otaexampleAGENT_TASK_PRIORITY,
                               NULL );

        if( xStatus != pdPASS )
        {
            LogError( ( "Failed to create OTA agent task:" ) );
        }
    }

    /****************************** Start OTA ******************************/

    if( xStatus == pdPASS )
    {
        /* Send start event to OTA Agent.*/
        xEventMsg.eventId = OtaAgentEventStart;
        OTA_SignalEvent( &xEventMsg );
    }

    /******************** Loop and display OTA statistics ********************/

    if( xStatus == pdPASS )
    {
        while( ( xOtaState = OTA_GetState() ) != OtaAgentStateStopped )
        {
            /* Get OTA statistics for currently executing job. */
            if( xOtaState != OtaAgentStateSuspended )
            {
                OTA_GetStatistics( &xOtaStatistics );

                LogInfo( ( " Received: %u   Queued: %u   Processed: %u   Dropped: %u",
                           xOtaStatistics.otaPacketsReceived,
                           xOtaStatistics.otaPacketsQueued,
                           xOtaStatistics.otaPacketsProcessed,
                           xOtaStatistics.otaPacketsDropped ) );
            }

            vTaskDelay( pdMS_TO_TICKS( otaexampleEXAMPLE_TASK_DELAY_MS ) );
        }
    }

    return xStatus;
}
```

このデモアプリケーションのハイレベルな流れは次のとおりです。
+ MQTT エージェントコンテキストを作成します。
+  AWS IoT エンドポイントに接続します。
+ OTA エージェントを初期化します。
+ OTA 更新ジョブを許可し、1 秒に 1 回の統計を出力するループ。
+ MQTT が切断されると、OTA エージェントのオペレーションを中断します。
+ 指数関数的に増える時間間隔とジッターを使用して再度接続を試みます。
+ 再接続されると、OTA エージェントのオペレーションを再開します。
+ エージェントが停止した場合は、1 秒遅らせて再接続を試みます。

## OTA エージェントイベントにアプリケーションコールバックを使用する
<a name="application-callback-ota"></a>

前の例では、`prvOtaAppCallback` を OTA エージェントイベントのコールバックハンドラーとして使用しました。(`OTA_Init` API コールの 4 番目のパラメータを参照)。完了イベントのカスタム処理を実装する場合は、OTA デモ/アプリケーションでデフォルトの処理を変更する必要があります。OTA プロセス中、OTA エージェントは次のイベント列挙値の 1 つをコールバックハンドラーに送信できます。これらのイベントをどのように処理するかは、アプリケーション開発者が決定します。

```
/**
 * @ingroup ota_enum_types
 * @brief OTA Job callback events.
 *
 * After an OTA update image is received and authenticated, the agent calls the user
 * callback (set with the @ref OTA_Init API) with the value OtaJobEventActivate to
 * signal that the device must be rebooted to activate the new image. When the device
 * boots, if the OTA job status is in self test mode, the agent calls the user callback
 * with the value OtaJobEventStartTest, signaling that any additional self tests
 * should be performed.
 *
 * If the OTA receive fails for any reason, the agent calls the user callback with
 * the value OtaJobEventFail instead to allow the user to log the failure and take
 * any action deemed appropriate by the user code.
 *
 * See the OtaImageState_t type for more information.
 */
typedef enum OtaJobEvent
{
    OtaJobEventActivate = 0,       /*!< @brief OTA receive is authenticated and ready to activate. */
    OtaJobEventFail = 1,           /*!< @brief OTA receive failed. Unable to use this update. */
    OtaJobEventStartTest = 2,      /*!< @brief OTA job is now in self test, perform user tests. */
    OtaJobEventProcessed = 3,      /*!< @brief OTA event queued by OTA_SignalEvent is processed. */
    OtaJobEventSelfTestFailed = 4, /*!< @brief OTA self-test failed for current job. */
    OtaJobEventParseCustomJob = 5, /*!< @brief OTA event for parsing custom job document. */
    OtaJobEventReceivedJob = 6,    /*!< @brief OTA event when a new valid AFT-OTA job is received. */
    OtaJobEventUpdateComplete = 7, /*!< @brief OTA event when the update is completed. */
    OtaLastJobEvent = OtaJobEventStartTest
} OtaJobEvent_t;
```

OTA エージェントは、メインアプリケーションのアクティブな処理中にバックグラウンドで更新を受け取ることができます。これらのイベントを配信する目的は、アクションを即時に実行できるかどうか、または他のアプリケーション固有の処理が完了するまで遅延する必要があるかどうかをアプリケーションが判断できるようにすることです。これによって、ファームウェアの更新後のリセットなどによるアクティブな処理中 (バキューム処理など) に、予期しないデバイスの中断を防ぐことができます。これらは、コールバックハンドラーによって受信されたたジョブイベントです。

**`OtaJobEventActivate `**  
このイベントがコールバックハンドラーによって受信された場合、すぐにデバイスをリセットするか、後でデバイスをリセットするようコールをスケジュールすることができます。これにより、必要に応じてデバイスのリセットとセルフテストフェーズを延期できます。

**`OtaJobEventFail`**  
このイベントがコールバックハンドラーによって受信されると、更新は失敗します。この場合、何もする必要はありません。ログメッセージを出力するか、アプリケーション固有の処理を行うことができます。

**`OtaJobEventStartTest`**  
セルフテストフェーズは、新しく更新されたファームウェアが正常に機能しているかどうかを判断する前に、実行およびテストを行い、更新されたファームウェアを最新の永続的なアプリケーションイメージにコミットするように意図されています。新しい更新が受信および認証され、デバイスがリセットされると、テストの準備ができ次第、OTA エージェントは `OtaJobEventStartTest` イベントをコールバック関数に送信します。開発者は、更新後にデバイスファームウェアが正しく機能しているかどうかを判断するために必要なテストを追加できます。デバイスファームウェアが自己テストによって信頼できると見なされた場合、コードは `OTA_SetImageState( OtaImageStateAccepted )` 関数を呼び出すことで、ファームウェアを新しい永続イメージとしてコミットする必要があります。

**`OtaJobEventProcessed`**  
`OTA_SignalEvent` によってキューに入れられた OTA イベントが処理されるため、OTA バッファの解放などのクリーンアップオペレーションを実行できます。

**`OtaJobEventSelfTestFailed`**  
現在のジョブで OTA セルフテストが失敗しました。このイベントのデフォルトの処理では、OTA エージェントをシャットダウンして再起動し、デバイスが前のイメージにロールバックされます。

**`OtaJobEventUpdateComplete`**  
OTA ジョブ更新完了の通知イベント。