「AWS SDK for javascript」を用いてMQTT通信を実現する

はじめに

 新たにモバイル向けアプリ開発を行う際に発生する開発言語の学習コストを、フレームワークを使用する事で下げることが可能です。当記事ではAndroid/iOSを共通のコードで開発できるApache Cordovaを使用し、スマートフォンからAWS IoT Coreへ、AWS SDK for javascriptを用いてMQTT通信を行うアプリ開発を紹介します。

概要

 モバイル向けアプリの市場が、スマートフォンの普及などを受けて拡大を続けています。[1] しかし、新たにモバイル向けのアプリ開発に挑戦するにあたって、Android向けにはJavaやKotlinなどのAndroid開発言語を、iOS向けには統合開発環境であるXcodeやSwiftなどのiOS開発言語を、それぞれ用意し学習しなければならず、学習コストも高いものとなっています。そこで、React NativeやApache Cordovaなどのモバイルアプリケーション開発フレームワークを使用することで、HTML5, CSS, JavaScriptを用いた開発を行うことが出来ます。本記事では、Apache Cordovaを用いて開発を行っていきます。

 また、IoT時代とも言われている昨今では、ますますIoT機器や周辺アプリケーションの開発が進んでいくことが予想できます。[2]その中で、IoT機器との通信に用いられるMQTT通信に着目しました。

 今回は、Apache Cordovaを利用して、スマートフォンからAWS IoT CoreへのMQTT通信を行うアプリケーションの開発について、2回にわたって紹介します。1回目の本記事では、「AWS SDK for javascript」を用いてMQTT通信を行います。開発環境の構築手順からAWSコンソールを利用した実行結果の確認までを説明していきます。

 Apache Cordovaとは
 オープンソースのモバイル向けアプリケーション開発フレームワークで、HTML5,CSS3, JavaScriptを使用してクロスプラットフォーム開発を行うことが出来ます。[3]
 Apache Cordovaでは様々な機能をカバーする多くのプラグインが用意されています。MQTT通信を行うプラグインも用意されており、これについては次回の記事で紹介します。 
 AWS IoT
 AWS(Amazon Web Service)では、100種類以上のクラウドコンピューティングサービスが提供されています。AWS IoTは、IoT デバイスを他のデバイスや、AWSのサービスに接続するサービスです。[4] MQTT, MQTT over WSS,  HTTPS, LoRaWANが用意されており、それぞれサーバーを用意することなく利用することが出来ます。
 ルールを設定することで、さらに別のAWSサービスへの接続を行うことが出来ます。 

使用するツール

 本記事では以下のツールを使用します。

 Apache Cordovaはスマートフォンアプリの統合開発環境であり、Android/iOSそれぞれ共通のコードで開発することが出来ます。しかし、アプリケーションのビルドにはAndroidではAndroid Studio、iOSではXcodeが必要となります。Android StudioはWindows/MacOS双方で使用できますが、XcodeはMacOSにのみ対応しているため、iOS向けアプリケーションのビルドにはMacを使用する必要があります。

 今回は、Windows10 + Androidをターゲットとした開発となっています。

1. Cordova
こちらを用いてモバイルアプリ開発を行います。
公式サイト:https://cordova.apache.org/

2. Android Studio
Cordovaを使用したモバイルアプリの開発・エミュレーターの実行に用います。
公式サイト:https://developer.android.com/studio

3. AWS IoT(Core)
MQTTブローカーとして使用します。また、アプリからのメッセージの受信の確認を行います。
開発者向けドキュメント:https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/what-is-aws-iot.html

4. Amazon Cognito
作成したweb・モバイルアプリケーションなどからAWSの各サービスへの接続を管理するサービスになります。アプリケーションにおけるユーザー管理などが出来ます。今回は、AWS IoT CoreのMQTTブローカーへの接続の認証に使用します。
開発者向けドキュメント:https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/what-is-amazon-cognito.html

各ツールの使用バージョン

 今回の実装における各ツールの使用バージョンの一覧です。使用するバージョンによっては、設定方法・UIなどにおいて記事内の説明と差異がある場合がありますので、注意してください。

No. ツール名 使用バージョン
1 node.js(npm) v14.17.3(6.14.13)
2 Apache Cordova 10.0.0
3 javac 1.8.0_291
4 Gradle 7.1.1
5 Android Studio 4.2.2
6 AWS 2021/11/01 時点のもの
7 Windows Windows 10 Home

開発環境の構築

 実際に、開発していくのに必要な開発環境の構築を行っていきます。Cordovaのインストール・Android Studioでの実行環境の構築、AWS IoT・Amazon Cognitoのセットアップを行います。

Apache Cordova + Android Studio

1. Cordovaのインストール

 CordovaのインストールにはNode.js(npm)が必要となります。Node.jsがまだインストールされていない場合は、こちら(https://nodejs.org/ja/)からインストーラーをダウンロードの後、実行し、表示に従ってインストールしてください。
 npmを使用してcordovaのインストール・アプリを作成します。

> npm install -g cordova
> cd [作業フォルダのパス]
> cordova create myApp
> cd myApp
> cordova platform add android

2. JDK(Java Development Kit)のインストール

2.1. インストール
 JDK(Java Development Kit)をインストールします。Javaアプリケーション開発に必要なツールがまとめられたパッケージです。AndoroidアプリケーションはJavaで動くため、こちらが必要になります。
 こちら(https://www.oracle.com/java/technologies/downloads/#java8)からインストーラーをダウンロードの後、実行し、表示に従ってインストールしてください。

2.2. 環境変数の設定
 JDKのダウンロードフォルダを環境変数に設定します。
 設定するJavaのインストールバージョンを確認します。

> javac -version
javac 1.8.0_291

 Windowsメニューの設定から「環境変数」と検索し、「システム環境変数を編集」を選択してください。
 下部「環境変数」を押すと環境変数の設定画面が表示されます。システム環境変数に「JAVA_HOME」を追加し、JDKをインストールしたフォルダ「例:C:\Program Files\Java\jdk1.8.0_291」を設定してください。

3. Gradleのインストール

3.1. インストール
 Gradleは、オープンソースのビルドツールになります。Androidアプリケーションのビルドに使用します。
 こちら(https://gradle.org/install/)からダウンロードします。ダウンロード後、展開し任意のフォルダに配置してください。

3.2. パスを通す
 先ほどと同じ手順で環境変数の設定画面を開きます。
 システム環境変数に「GRADLE_HOME」を追加し、先ほどGradleを配置したフォルダ「例:C:\Program Files\gradle-7.1.1」を設定します。同じくシステム環境変数の「Path」を選択(なければ新規作成)し、「%GRADLE_HOME%\bin」を追加してください。

4. Android Studioのインストール

4.1. インストール
 こちら(https://developer.android.com/studio)からインストーラーをダウンロードの後、実行し、表示に従ってインストールしてください。

4.2. 環境変数の設定
 Android StudioのToolsから「SDK Manager」を開きます。画面上部に「Android SDK Location」という欄がありますので、SDKのパスを取得します。
 先ほどと同じ手順で環境変数の設定画面を開きます。
 システム環境変数に「ANDROID_SDK_ROOT」を追加し、取得したパスを設定してください。

4.3. ライセンスに同意

> cd C:\Users\[ユーザー名]\AppData\Local\Android\Sdk\tools\bin
> sdkmanager --licenses

表示された各項目に問題がなければyを入力してください。

AWS

1. AWS IoT

 AWS IoT CoreのMQTTブローカーに接続するためのエンドポイントURLを取得します。
 今回は、MQTTでの接続の認証はAmazon Cognitoを利用します。そのため、証明書の作成や設定などを行う必要はありません。
 AWSのコンソールからIoT Coreを選択します。左メニュー下部の設定を選択すると、画像赤枠部分に「デバイスデータエンドポイント」がありますので、そちらを取得します。

2. Amazon Cognito

 AWSのコンソールからCognitoを選択します。「IDプールの管理」を選択し、新しいIDプールを作成します。「認証されていないIDに対してアクセスを有効にする」にチェックを入れます。
 プールを作成すると、画像の画面に切り替わるため、画像赤枠部分からポリシードキュメントを編集します。

 下記のように、MQTTのメッセージのpublishを行うのに最低限必要なポリシーをアタッチします。認証されていないIDに対してのロールですので、不要なものはアタッチしないよう注意してください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
          "Effect": "Allow",
          // 中略
          "Resource": [
            "*"
          ]
        },  // カンマから追加
        {
            "Effect": "Allow",
            "Action": [
                "iot:Connect",
                "iot:Publish"
            ],
            "Resource": [
              "arn:aws:iot:us-east-1:123456789012:client/*",
              "arn:aws:iot:us-east-1:123456789012:topic/${iot:ClientId}/*"
            ]
        }  // ここまで
    ]
}

 作成出来たら、サンプルコード画面を開きます。プラットフォームで「JavaScript」を選択し、画像赤枠内のリージョン・IdentityPoolIdを控えておいてください。

実装

 いよいよ、実装の工程について説明します。開発には、Android studioを使用します。 Android Studioから、先ほど作成したアプリケーション(例:MyApp)のフォルダ内  platforms > android を開きます。書き換えていくファイルは、app > src > main > assets > www > index.htmlになります。
 もともとのindex.htmlの中身は削除してしまって構いません。その場合、index.jsの中身も削除するようにしてください。

1. UI部分の作成

 今回は、簡易的にトピック名・送信するメッセージの入力フォームと送信ボタンのみ作成します。

<h1>MQTT通信</h1>
トピック <input type="text" id="topic">
<br>
メッセージ <input type="text" id="message">
<br>
<button id="send-btn">送信</button>

2. AWS SDK・jQueryの読み込み

 こちら(https://github.com/aws/aws-iot-device-sdk-js)のSDKを使用します。
 以下の手順でaws-iot-sdk-browser-bundle.jsが取得できます。

> git clone https://github.com/aws/aws-iot-device-sdk-js.git
> cd aws-iot-device-sdk-js
> npm install -g browserify
> npm run-script browserize

 browserフォルダ配下に、aws-iot-sdk-browser-bundle.jsが生成されていますので、こちらをindex.htmlと同じ階層のjsフォルダ内に配置します。
 今回は、ボタンの制御にjQueryを使用しています。こちらは使用しなくても実装が可能です。こちら(https://jquery.com/download/)からダウンロードして同様にjsフォルダ内に配置してください。
 以下の2行で2つのファイルを読み込みます。

<script src="js/jquery-3.5.1.js"></script>
<script src="js/aws-iot-sdk-browser-bundle.js"></script>

3. Java Scriptの実装

 Java Scriptの実装を行っていきます。

3.1. ライブラリの読み込みと定数の定義

 aws-iot-sdk-browser-bundle.jsを読み込むことによって、’aws-iot-device-sdk’, ‘aws-sdk’をロードすることが出来ます。
 PoolID/regionにはCognito作成時に取得したもの、hostにはAWS IoTで取得したエンドポイントを設定してください。
 clientIdは、AWS IoTへの接続を識別するもので、任意のものを指定してください。

var awsIot = require('aws-iot-device-sdk');
var AWS = require('aws-sdk');
const PoolId = "ap-northeast-1:XXXXXXXX";
const region = "ap-northeast-1";
const host = "XXXXXXX-ats.iot.ap-northeast-1.amazonaws.com";
var clientId = "sample";

3.2. 認証情報を取得する

 CognitoからAWS IoTへの接続に用いる認証情報を取得します。
  cognitoidentity = new AWS.CognitoIdentity() で認証アイデンティティオブジェクトを生成しています。一時的な認証情報を生成するためのものです。
  cognitoidentity.getId() で生成したアイデンティティオブジェクトのidを取得し、 getCredentialsForIdentity() で認証情報が生成できます。これらは一時的なものであり、取得のたびに結果が変わります。また、結果が返却されるのに時間がかかることがあるため、非同期処理として実行します。

async function getCredentials(){
    AWS.config.region = region;
    var cognitoidentity = new AWS.CognitoIdentity();

    var params = {
        IdentityPoolId: PoolId
    };
    const identityId = await cognitoidentity.getId(params).promise();

    const data = await cognitoidentity.getCredentialsForIdentity(identityId).promise();

    var credentials = {
        accessKey: data.Credentials.AccessKeyId,
        secretKey: data.Credentials.SecretKey,
        sessionToken: data.Credentials.SessionToken
    };

    return credentials;
}

3.3. AWS IoTへ接続

 上で取得した認証情報を使用して、AWS IoTに接続します。
  awsIot.device() のパラメータに、はじめに定義した接続先情報や前項で取得した認証情報などを渡すことで接続されます。

async function connect(){
    credentials = await getCredentials(); // Credentialsの取得

    deviceIot = awsIot.device({
        region: region,
        clientId: clientId,
        accessKeyId: credentials.accessKey,
        secretKey: credentials.secretKey,
        sessionToken : credentials.sessionToken,
        protocol: 'wss',
        port: 443,
        host: host
    });

    return deviceIot;
}

3.4. Publish

 送信ボタンの押下を検出し、AWS IoTに接続、メッセージを送信します。
 ボタンの押下はjQueryの .on(“click”) メゾットで検出しています。
 入力されたトピック名・メッセージを取得し、メッセージはJSONデ形式に変換しています。AWS IoTコンソール上で受信を確認する際にJSON形式であると綺麗に表示出来るため変換していますが、文字列のままでも送信が可能です。
 deviceIot.publish()のパラメータにトピック・メッセージ・オプション(今回は指定なし)・コールバックを指定します。コールバックではエラー内容が取得でき、それを利用してエラー処理を記載しています。

$(function(){
    deviceIot = connect();

    $("#send-btn").on("click", function(){
        var topic = $("#topic").val();
        var message = $("#message").val();

        var payload = {
            message: message
        };
        console.log(message);
        deviceIot.publish(topic, JSON.stringify(payload), undefined, function(err){
            if( err ){
                console.log('iot_publish error: ' + err);
                return;
            } else {
                console.log(topic + " : " + payload);
            }
        });
    });
});

3.5. AWS IoTコンソールでのメッセージの確認方法

 アプリケーションから送信したメッセージが正しく送信されているかどうか、AWS IoTコンソールで受信して確認します。
 AWSコンソールからIoT Coreを選択し、AWS IoTコンソールを開きます。左メニューから テスト > MQTT テストクライアント を開きます。「トピックをサブスクライブする」から画像赤枠部分「トッピクをフィルター」にサブスクライブしたいトピックを入力し、サブスクライブボタンを押下することでサブスクライブが開始されます。
 サブスクライブするトピック名には、ワイルドカード(+)が使用出来ます。
 メッセージを受信すると、画面下部に受信したメッセージ内容が表示されます。

実行

 実際にアプリケーションをAndroid Studioのデバッガーを用いて実行し、メッセージの送信を確認します。

1. エミュレーターの準備

 Android Studioの最上部ツールバーから Tools > AVD Managerを開きます。「Create Virtual Device」をクリックすると、エミュレーターで使用可能なデバイス一覧が表示されますので、使用したいデバイスを選択し、表示に従って登録してください。
 実際のAndroid端末を使用する場合は、PCにUSB接続してください。

2. 実行

 先ほどのAWS IoTコンソールにて使用したいトピックを入力し、サブスクライブを開始します。
 Android Studio上部ツールバーから「Debug」を選択(Shift+F9でも可)すると、デバッガーの実行がスタートします。画像のように作成したアプリケーションがエミュレーター上で実行されます。
 アプリケーションの入力フォームに送信したいトピック名・メッセージを入力し、送信ボタンを押下します。
 送信したメッセージがAWS IoTコンソール上で確認できれば成功です。

3. AWS IoTから他のAWSサービスに接続したい場合

 最後に、AWS IoTで受信したメッセージをさらに他のAWSサービスに送信する方法を簡単に説明します。
 AWS IoTコンソールから ACT > ルール を選択し作成ボタンを押下すると、ルールの新規作成画面が開きます。「ルールクエリステートメント」に受信したいトピックなどの情報を設定、「1 つ以上のアクションを設定する」から実行するAWSサービスを選択し、ルールを作成します。
 設定したトピックにメッセージが送信されると、自動的にアクションに指定したAWSサービスに受信メッセージが送信されます。

まとめ

 本記事では、Apache Cordova及びAWS SDK for JavaScriptを利用してMQTT通信を行うアプリケーションの開発について、開発環境の構築の手順からAWSコンソール上での実行結果の確認までを説明しました。
 AWS SDKを用いての実装では、AWS IoTへの接続に加えて、今回利用したCognitoや他のAWSサービスとの連携を容易に行うことが出来ます。
 さらにAWS IoTでルールを設定することで、様々なAWSサービスへのデータ送信が可能になります。
 本記事ではAWS IoTにメッセージを送信していますが、自分で用意したMQTTブローカーや他のサーバーに送信する場合は、Cordova MQTTプラグインなどを利用する必要があります。そこで次回は、Cordova MQTTプラグインを利用して同様のアプリケーションを実装する方法について説明します。

参考資料

[1] “平成28年版 情報通信白書 第一部 第二章 第二節” 総務省
https://www.soumu.go.jp/johotsusintokei/whitepaper/ja/h28/html/nc122230.html

[2] “平成28年版 情報通信白書 第一部 第二章 第一節” 総務省
https://www.soumu.go.jp/johotsusintokei/whitepaper/ja/h28/pdf/n2100000.pdf

[3] “Architectural overview of Cordova platform”
https://cordova.apache.org/docs/en/latest/guide/overview/index.html

[4] “AWS IoTとは” AWS IoT Core デベロッパーガイド
https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/what-is-aws-iot.html

[5] “Amazon Cognito とは”Amazon Cognito デベロッパーガイド
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/what-is-amazon-cognito.html

[6] “パブリッシュ/サブスクライブポリシーの例”  AWS IoT Core デベロッパーガイド
https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/pub-sub-policy.html

[7] “Class: AWS.CognitoIdentity” AWS SDK for Javascript ドキュメント
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentity.html