受信処理の実装

次に、MQTT ライブラリーを使ってプッシュ通知の受信処理を実装します。

MQTT を使用する場合、他のプッシュ通知ネットワークを使う場合と異なり、特別な設定を行う必要はありません。プログラムだけで全ての処理が完結します。

MQTT エンドポイントの取得

初めに、Kii Cloud を呼び出して、MQTT のエンドポイントを取得する部分までを実装します。

main.js を以下のコードに置き換えてください。

function execute() {
  var username = "user1";
  var password = "123ABC";
  KiiUser.authenticate(username, password).then(
    function(theUser) {
      var development = false;
      return KiiUser.getCurrentUser().pushInstallation().installMqtt(development);
    }
  ).then(
    function(response) {
      var installationID = response.installationID;
      return KiiUser.getCurrentUser().pushInstallation().getMqttEndpoint(installationID);
    }
  ).then(
    function(response) {
      var username = response.username;
      var password = response.password;
      var mqttTopic = response.mqttTopic;
      alert("Success installation username:" + username + ", password: " + password + ", mqttTopic:" + mqttTopic);
    }
  ).catch(
    function(error) {
      var errorString = error.message;
      alert("Error in Initialization: " + errorString);
    }
  );
}

ここでは、次の処理を行っています。

  1. ユーザーのログイン

    先ほど作成したユーザーを使ってログインします。Kii Cloud でのプッシュ通知の配信先はユーザーであるため、まずはユーザーのログインが必要です。

    ユーザー名 user1、パスワード 123ABC でログインします。成功すると、次の then ブロックの関数が、失敗すると catch ブロックの関数がそれぞれ呼び出されます。

  2. MQTT へのインストール

    ログインに成功すると、この処理が行われます。

    プッシュ通知を利用するには、Kii Cloud 上にプッシュ通知の対象となるユーザーの情報をインストールする必要があります。

    ログイン中のユーザーの pushInstallation()KiiPushInstallation を取得し、その installMqtt() を呼び出して MQTT 用にインストール処理を行います。

  3. エンドポイントの取得

    インストール処理が成功したら、その MQTT 用のエンドポイントを getMqttEndpoint() で取得します。

エンドポイントの取得が成功したら、最後の then ブロックの処理が行われます。最終的には MQTT クライアントからの接続を行いますが、上のコードでは MQTT 接続用のユーザー名、パスワード、MQTT トピックを alert で表示しています。

実行すると、MQTT 接続用の情報が表示されるはずです。

MQTT クライアントの実装

alert("Success installation ...") がある then ブロックを以下のように書き換えて、MQTT クライアントを使って Kii Cloud に接続できるようにします。

実装は選択したライブラリーによって異なります。各タブページで実装を確認してください。

  •   ......
      ).then(
        function(response) {
          var username = response.username;
          var password = response.password;
          var mqttTopic = response.mqttTopic;
    
          var endpoint = "wss://" + response.host + ":" + response.portWSS + "/mqtt";
          var client = mqtt.connect(endpoint, {
            username: username,
            password: password,
            clientId: mqttTopic,
          });
    
          client.on("connect", function() {
            console.log("MQTT Connected");
            client.subscribe(mqttTopic, function() {
              console.log("MQTT Subscribed");
            });
          });
    
          client.on("message", function(topic, message, packet) {
            if (topic === mqttTopic) {
              var payload = JSON.parse(message.toString());
              var myMessage = payload.mymessage;
              alert("Message Arrived:" + myMessage);
            }
          });
    
          client.on("error", function(error) {
            alert("Error in MQTT" + error);
          });
        }
      ).catch(
      ......
  •   ......
      ).then(
        function(response) {
          var username = response.username;
          var password = response.password;
          var mqttTopic = response.mqttTopic;
    
          var endpoint = "wss://" + response.host + ":" + response.portWSS + "/mqtt";
          var clientId = mqttTopic;
          var client = new Paho.MQTT.Client(endpoint, clientId);
    
          client.onConnectionLost = onConnectionLost;
          client.onMessageArrived = onMessageArrived;
    
          client.connect({onSuccess:onConnect,
            userName:username,
            password:password,
          });
    
          function onConnect() {
            console.log("MQTT Connected");
            client.subscribe(mqttTopic);
          }
    
          function onConnectionLost(responseObject) {
            if (responseObject.errorCode !== 0) {
                alert("MQTT Connection Lost:" + responseObject.errorMessage);
            }
          }
    
          function onMessageArrived(message) {
            if (message.destinationName === mqttTopic) {
              var payload = JSON.parse(message.payloadString);
              var myMessage = payload.mymessage;
              alert("Message Arrived:" + myMessage);
            }
          }
        }
      ).catch(
      ......

いずれの実装でも、MQTT ブローカーとして動作する Kii Cloud への接続処理と、MQTT クライアントのコールバックの設定を行っています。

接続処理

関数の引数 response には、Promise により getMqttEndpoint() で取得した MQTT ブローカーの情報が渡されています。response から接続に必要な情報を取得して MQTT クライアントを初期化します。取得できるパラメーターの詳細については、MQTT コネクションの確立 をご覧ください。

初めに、接続先 URL を変数 endpoint に作成します。接続先は、wss://ホスト名:ポート番号/mqtt の形式です。ホスト名は response.host、ポート番号は response.portWSS で取得できます。

response で渡されるポート番号は 4 種類あり、TCP と WebSocket の差違、SSL/TLS の有無により、4 通りの接続方法がサポートされますが、通常は WebSocket を SSL/TLS ありで利用します。多くの JavaScript 用 MQTT ライブラリーでは、ブラウザーからの利用時には、TCP の直接使用ではなく、WebSocket の利用が想定されています。また、安全のため接続時には SSL/TLS を使用するのが適切です。

その他、接続に必要な情報は以下のとおりです。

  • Kii Cloud では、接続時に MQTT のクライアント ID として MQTT トピック名を指定します。

  • MQTT 接続時のユーザー名、パスワードは response から取得した値を指定します。

コールバックの設定

次に、コールバックを設定します。いずれのライブラリーを使う場合でも、以下の 3 つのイベントが発生した場合の処理を定義しています。

  • 接続完了時の処理

    接続完了時のコールバック関数では、response.mqttTopic で得られた MQTT トピックを講読する処理を行います。

    この MQTT トピックは、MQTT を使ってプッシュ通知の通信路を構築するためのものです。MQTT 接続 1 つに対して 1 つの MQTT トピックが Kii Cloud によって割り当てられます。この MQTT トピックを講読することによって、プッシュ通知をサーバー側からの PUBLISH コマンドとして受信できます。

    なお、Kii Cloud が提供している ユーザープッシュ通知(Push to User) のトピックと MQTT トピックは別の概念です。Push to User を使用する場合、トピックの講読処理は別に必要です。詳細は、Kii Cloud SDK for Thing の講読処理を説明した プッシュ通知 を参考にしてください。

  • コネクション切断時の処理

    コネクションの切断時のコールバック関数では、エラーメッセージの表示を行います。

    今回の 2 つのライブラリーでは、コネクションの接続が切れた際にエラーが通知される仕様です。Web アプリの仕様によっては、再接続処理などを作り込む必要があるかもしれません。

  • プッシュメッセージが届いた場合の処理

    プッシュメッセージが届いた際のコールバック関数では、メッセージを画面表示します。

    関数が呼び出されたとき、いずれのライブラリーでも、Kii Cloud からの PUBLISH コマンドの詳細を取得できます。

    まず、PUBLISH コマンドの発行元トピック名を調べます。発行元のトピック名が、講読済みのトピック名 mqttTopic と同じであれば、それはプッシュ通知による PUBLISH コマンドです。

    一致している場合は、PUBLISH コマンドのペイロードから、Kii Cloud で発生したイベントの詳細を JSON 形式の文字列として取得します。

    PUBLISH コマンドは様々な目的で受信するため、サーバー側からの PUBLISH コマンドを受け取った際には、必ず MQTT トピック名をチェックするように実装してください。また、未知の MQTT トピック名を持つ PUBLISH コマンドは、将来の拡張のため無視するように実装してください。

    今回は、後述の実行テストのステップで、以下のように mymessage フィールドにメッセージを設定します。受信処理ではペイロードの JSON を解析して mymessage フィールドを取り出して画面表示しています。

    {
      "sourceURI":"kiicloud://users/727f20b00022-8d18-5e11-991f-06db2509",
      "mymessage":"Hello",
      "senderURI":"kiicloud://admins/APP_ADMIN"
    }
    


なお、MQTT では一定時間送信データがない場合、クライアントから PINGREQ コマンドを送信しないとコネクションが切断されます。今回利用している 2 つのライブラリーでは、これらを自動送信する実装のため、PINGREQ に対する特別な考慮は不要です。

次のステップ テストメッセージの送信 に進みましょう。


<< ライブラリーの組み込み テストメッセージの送信 >>