クイック・スタート・チュートリアル

Application Mashup (WireCloud) course @ https://fiware-academy.readthedocs.io/

Presenter Notes

クイック・スタート・チュートリアル

イントロダクション

Presenter Notes

イントロダクション

必要なもの:

  • エディタ
  • zip ツール
  • gravatar アカウント/プロフィール

Presenter Notes

イントロダクション

リファレンス実装

このチュートリアルで作成されたウィジェットとオペレータのリファレンス実装は、 次の github リポジトリにあります :

https://github.com/wirecloud-fiware/quick-start-development-tutorial

チュートリアルを完了した後、またはストールした場合に備えて、 リファレンス実装を見ることをお勧めします。

Presenter Notes

クイック・スタート・チュートリアル

基本チャット・ウィジェット

Presenter Notes

基本チャット・ウィジェット

初期バージョン

最初のステップは空のウィジェットを作ることです。メタデータと基本的な HTML を定義したものです。メタデータは config.xml ファイルに書き込まれます。 これは次のような内容です :

<?xml version='1.0' encoding='UTF-8'?>
<widget xmlns="http://wirecloud.conwet.fi.upm.es/ns/macdescription/1" vendor="CoNWeT" name="basic-chat" version="0.1">
    <details>
        <title>Basic chat</title>
        <homepage>https://github.com/wirecloud-fiware/quick-start-development-tutorial</homepage>
        <authors>Miguel Jimenez &lt;mjimenez@fi.upm.es&gt;</authors>
        <contributors>Álvaro Arranz &lt;aarranz@fi.upm.es&gt;</contributors>
        <email>wirecloud@conwet.com</email>
        <image>images/chat_logo.png</image> <!-- 170x80 -->
        <description>Basic chat functionality and WireCloud features demonstrator</description>
        <longdescription>README.md</longdescription>
        <license>Apache License 2.0</license>
        <licenseurl>http://www.apache.org/licenses/LICENSE-2.0.html</licenseurl>
        <doc>doc/developer-guide.md</doc>
    </details>
    <contents src="index.html" useplatformstyle="true"/>
    <rendering width="5" height="24"/>
</widget>

Presenter Notes

基本チャット・ウィジェット

初期バージョン

そのテンプレートは、Markdown を使って書くことができるより詳細な説明と共に、 著者/ベンダーのようなウィジェットのメタデータを示します。

ルート要素の属性として示されている vendor, name そして version に注意してください。WireCloud の設定によっては、同じバージョン/名前/ベンダーの ウィジェットを2回アップロードすることが許可されないので、ウィジェットの 新しいバージョンをアップロードするには、バージョン、サブバージョン、 またはリビジョン番号を増やす必要があります。さらに、他のユーザがすでに バージョン、名前、およびベンダーが同じウィジェットをアップロードした場合、 WireCloud はウィジェットをアップロードしないため、ベンダーを変更する必要が あります。

2つ目に注目すべき要素は、rendering 要素です。ウィジェットのサイズに 関する基本情報と、メインの HTML ファイルへの参照を含む要素です。 このようなファイルはウィジェットへのエントリポイントとなり、JavaScript または CSS ファイルへの参照を含みます。

Presenter Notes

基本チャット・ウィジェット

初期バージョン

config.xmlindex.html という名前で示されている基本的な HTML を以下に示します。このドキュメントには、ユーザの写真とニックネームの 基本ヘッダー、メッセージのパネル、およびメッセージ送信の基本フォームが 含まれています。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8"></meta>
        <script type="text/javascript" src="js/main.js"></script>
        <link rel="stylesheet" type="text/css" href="css/style.css" />
    </head>
    <body>
        <div id="header">
            <img id="photo"id="photo"  alt="Profile photo" max-height="60" max-width="60" />
            <h2 id="username">Username</h2>
        </div>
        <div id="conversations"></div>
        <div id="footer">
            <input id="input" type="text" /><button id="send" type="button">Send</button>
        </div>
    </body>
</html>

Presenter Notes

基本チャット・ウィジェット

初期バージョン

この HTML コードは js/main.js JavaScript ファイルを参照します。 JavaScript ファイルには必要なコードが含まれています。JavaScript コードについては後で詳しく説明します。さらに、チャット・アプリケーションの 基本的なスタイルを含む CSS ファイルが参照されています。

body {  padding: 0;
        margin: 0;
        font-family: sans-serif;
        color: #333;}
#photo {padding: 3px;
        border: 2px solid #eaeaea;
        max-height: 48px;
        max-width: 48px;
        float:left;}
.sent, .received {
        min-height: 36px;
        padding: 2px;
        border: 1px solid #eaeaea;
        border-radius: 5px;}
.sent {  margin: 1px 35px 1px 1px;}
.received{ margin: 1px 1px 1px 35px;
        text-align: right;}
.received > p{ display: inline;}
.sent > img{ max-height: 28px;
        max-width: 28px;
        margin: 2px;
        float:left;}
.sent > p{ display:inline;}
.received > img{ max-height: 28px;
        max-width: 28px;
        margin: 2px;
        float:right;}
#username { display: inline;}
#conversations { height: 65%;
        overflow: scroll;}
#footer{position: fixed;
        bottom: 0;}
#header{height:60px;}
body,html { height: 100%;}

Presenter Notes

基本チャット・ウィジェット

初期バージョン

最後に、参照先のjs/main.js が作成されます。ここでは、クロージャー、 init() 関数、そして HTML インターフェースを扱うための 2つの関数のようないくつかの基本的な要素を含みます。

(function() {
    "use strict";

    // object with the data received from gravatar
    var userData = null;

    function init() {
        document.getElementById("send").onclick = sendBtnHandler;
        getInfoFromGravatar();
    }

    function sendBtnHandler(e) {
    }

    function createMsgDiv(text,imageSrc,received,id){
        var newMsgP = document.createElement('p');
        var newMsgImg = document.createElement('img');
        var newMsgDiv = document.createElement('div');
        newMsgP.innerHTML = text;
        newMsgP.id = id;
        newMsgImg.src = imageSrc;
        newMsgImg.alt = 'User profile img';
        newMsgDiv.className=(received)?'received':'sent';
        newMsgDiv.appendChild(newMsgImg);
        newMsgDiv.appendChild(newMsgP);
        var conversations = document.getElementById('conversations');
        conversations.appendChild(newMsgDiv);
        conversations.scrollTop = newMsgDiv.offsetTop;
    }

    function getInfoFromGravatar() {
        // Put the info in userData variable
    }

    function printUserData(user_data) {
        document.getElementById('username').innerHTML = user_data.entry[0].displayName;
        document.getElementById('photo').src = user_data.entry[0].thumbnailUrl;
    }

    document.addEventListener('DOMContentLoaded', init.bind(this), true);

})();

Presenter Notes

基本チャット・ウィジェット

設定を追加

最初に追加する機能は設定です。Widget の設定は config.xml で宣言する必要があり、 後で、WireCloud JavaScript API を介してアクセスされます。ユーザの gravatar プロファイルを取得するための設定の宣言は、次のようになります :

<preferences>
    <preference name="gravatar" type="text" label="Gravatar URL" description="URL to the gravatar profile of the user" />
</preferences>

この <preferences> セクションはルート要素 <widget> の内側になければなりません。 これで、選択した name を使ってその値にアクセスできます。次の行は getInfoFromGravatar() 関数内にあるため、特定の URL に HTTP リクエストを送信できます。

var gravatarURL = MashupPlatform.prefs.get('gravatar');

Presenter Notes

基本チャット・ウィジェット

設定を追加

これだけをした場合、ユーザが自分のプロフィールを表示すると、Gravatar からプロフィールを取得するためにウィジェットをリロードする必要があります。 賢く物事をやるために、どんな設定変更についてもプラットフォームから通知され、 それに応じて反応しています。この場合は、getInfoFromGravatar() をもう一度呼び出します。 次のコードはinit() 関数の中に入ります :

    MashupPlatform.prefs.registerCallback(function(new_values) {
        if ('gravatar' in new_values) {
            getInfoFromGravatar();
        }
    });

Presenter Notes

基本チャット・ウィジェット

HTTP リクエストを実行

ユーザから他の情報を収集するために HTTP リクエストを送信します。 Gravatar は JSON バージョンのプロファイルを同じ URL で提供し、拡張子 .json を追加します。そのため、それがリクエストのベース URL になります。

基本的な HTTP リクエストは次のようになります :

    MashupPlatform.http.makeRequest(url, {
        method: 'GET',
        onSuccess: function(response) {
            var user_data;
            user_data = JSON.parse(response.responseText);
            if (user_data.error) {
                // handle error
                onError();
            } else {
                // perform actions
            }
        },
        onError: function() {
            onError();
        }
    });

Presenter Notes

基本チャット・ウィジェット

HTTP リクエストを実行

この構造は、取得したユーザ設定 gravatarURL と文字列 json を連結した結果の URL で呼び出されます。実行されるアクションは、userData 変数にデータを格納し、 以前に作成した printUserData() 関数を使用してそれをウィジェットに 表示させることです :

var url = gravatarURL + '.json';

...

    onSuccess: function(response) {
        var user_data;
        user_data = JSON.parse(response.responseText);
        if (user_data.error) {
            onError();
        } else {
            userData = user_data;
            printUserData(user_data);
        }
    }

Presenter Notes

基本チャット・ウィジェット

HTTP リクエストを実行

gravatar から取得した userData は、例えば print UserData() のように、 その情報にアクセスするために使われる単純な構造を持ちます :

{
    "entry": [{
        "id": "9508921",
        "hash": "61ac3cca6452efd339cb85c7864c147b",
        "requestHash": "mjimenezganan",
        "profileUrl": "http:\/\/gravatar.com\/mjimenezganan",
        "preferredUsername": "mjimenezganan",
        "thumbnailUrl": "http:\/\/2.gravatar.com\/avatar\/61ac3cca6452efd339cb85c7864c147b",
        "photos": [{
            "value": "http:\/\/2.gravatar.com\/avatar\/61ac3cca6452efd339cb85c7864c147b",
            "type": "thumbnail"
        }],
        "name": {
            "givenName": "Miguel",
            "familyName": "Jim\u00e9nez"
        },
        "displayName": "mjimenezganan",
        "aboutMe": "More info on www.twitter.com\/miguel_jimg",
        "currentLocation": "Spain",
        "urls": []
    }]
}

Presenter Notes

基本チャット・ウィジェット

ワイヤリングによる送受信

ウィジェットのチャット機能は、WireCloud のワイヤリング・メカニズムを 介して行われます。まず最初に、入力エンドポイントと出力エンドポイントを config.xml ファイルで宣言する必要があります :

<wiring>
    <outputendpoint name="sendMsg" type="text" label="Send a message" description="The messages sent by the user are sent through this output endpoint" friendcode="message"/>
    <inputendpoint name="receiveMsg" type="text" label="Receive a message"  description="This is where messages sent by other widgets can be received" friendcode="message" />
</wiring>

メッセージの送信は、宣言されたとおりに出力エンドポイント名をリファレンスする MashupPlatform.wiring.pushEvent() 関数を呼び出すことを意味します。

MashupPlatform.wiring.pushEvent('sendMsg', text);

Presenter Notes

基本チャット・ウィジェット

ワイヤリングによる送受信

sendBtnHandler() に追加します。メタデータ、つまり送信者の画像を取得することを 可能にする Gravatar ハッシュを含むメッセージを送信できるようにするために、 JSON シリアライズ。オブジェクトが送信されます :

function sendBtnHandler(e) {
    var msgToSend = {};
    msgToSend.msg = document.getElementById("input").value;
    if (msgToSend.msg !== "" && userData != null) {
        msgToSend.hash= userData.entry[0].hash;
        MashupPlatform.wiring.pushEvent('sendMsg', JSON.stringify(msgToSend));
    }
}

Presenter Notes

基本チャット・ウィジェット

ワイヤリングによる送受信

メッセージはワイヤリングを通じて送信されますが、ウィジェットは他のウィジェットの メッセージを受信して会話パネルに表示する必要があります。これはプラットフォーム上で コールバック関数を登録することで実行され、特定の入力エンドポイントで受信された メッセージを登録します。その名前で識別されます。 init() 機能で、次のように記述します :

MashupPlatform.wiring.registerCallback('receiveMsg', processMsg);

Presenter Notes

基本チャット・ウィジェット

ワイヤリングによる送受信

そして、望ましい振る舞いを示すために processMsg() 関数を作成しなければなりません。 今回の場合は、会話パネルでメッセージを作成します。メッセージはシリアライズされた JSON オブジェクトとして送信されるため、それらの要素にアクセスするために デシリアライズされます。それは自身のメッセージを検出しそれらを異なった CSS スタイルを送信したように表示するので、少しトリッキーです。これがエコーの動作です。

function processMsg(event_data) {
    var receivedMsg = JSON.parse(event_data);
    if (userData != null && receivedMsg.hash !== userData.entry[0].hash) {
        createMsgDiv(receivedMsg.msg, 'http://www.gravatar.com/avatar/' + receivedMsg.hash, true, receivedMsg.id);
    } else { // My message, echo, mark as sent
        createMsgDiv(receivedMsg.msg,'http://www.gravatar.com/avatar/' + receivedMsg.hash, false, receivedMsg.id);
        document.getElementById(receivedMsg.id).parentElement.className = 'sent'; 
    }
}

Presenter Notes

クイック・スタート・チュートリアル

基本的な NGSI チャット・オペレータ

Presenter Notes

基本的な NGSI チャット・オペレータ

初期オペレータ

オペレータは config.xml 宣言ファイルで定義され、その動作を含む 1つまたは複数の JavaScript ファイルを参照します。

ウィジェットと同様に、config.xml には、競合や WireCloud によるオペレータの拒否を避けるために、ベンダー、名前、および バージョン情報を更新する必要があります。

<?xml version='1.0' encoding='UTF-8'?>
<operator xmlns="http://wirecloud.conwet.fi.upm.es/ns/macdescription/1"
    vendor="CoNWeT" name="ngsi-chat-op" version="0.1.1">
    <details>
        <title>NGSI chat operator</title>
        <homepage>https://github.com/wirecloud-fiware/quick-start-development-tutorial</homepage>
        <authors>Miguel Jiménez</authors>
        <email>mjimenez@fi.upm.es</email>
        <image>images/operator_logo.png</image> <!-- 170x80 -->
        <description>Connect to Orion Context Broker through NGSI WireCloud API for chat room</description>
        <longdescription>README.md</longdescription>
        <license>Apache License 2.0</license>
        <licenseurl>http://www.apache.org/licenses/LICENSE-2.0.html</licenseurl>
        <doc>doc/developer-guide.md</doc>
    </details>
    <scripts>
        <script src="js/main.js"/>
    </scripts>
</operator>

Presenter Notes

基本的な NGSI チャット・オペレータ

初期オペレータ

このウィジェットには、NGSI サーバの URL を簡単に示すための設定と、ウィジェット/ オペレータからアクセスするためのプロキシがあります。 さらに、chatroom 設定が追加されました。

    <preferences>
        <preference name="ngsi_server"
            type="text" label="NGSI server URL"
            description="URL of the Orion Context Broker to use for retrieving entity information"
            default="http://orion.lab.fiware.org:10026/"/>
        <preference name="ngsi_proxy"
            type="text"
            label="NGSI proxy URL"
            description="URL of the PubSub Context Broker proxy to use for receiving notifications about changes"
            default="https://ngsiproxy.lab.fiware.org/"/>
        <preference name="chatroom"
            type="text"
            label="Chat room"
            description="Chat room to send and receive messages"
            default="Startup Weekends"/>
    </preferences>

Presenter Notes

基本的な NGSI チャット・オペレータ

初期オペレータ

ワイヤリングもウィジェットで使用されています。受信したメッセージをウィジェットに 送り返し、ユーザ・メッセージを NGSI API に転送します :

    <wiring>
        <outputendpoint name="toBeReceived"
            type="text"
            label="Messages from NGSI"
            description="Forward a message to a chat widget"
            friendcode="message" />
        <inputendpoint name="toBeSent"
            type="text"
            label="Message to NGSI"
            description="Receive messages to be sent to the chat room"
            friendcode="message" />
    </wiring>

Presenter Notes

基本的な NGSI チャット・オペレータ

初期オペレータ

基本的な JavaScript ファイルは以下に書かれていて、初期化機能、設定とワイヤリング、 サブスクリプションといくつかのスケルトンを含みます:

(function() {

    "use strict";

    var chatroom = null;
    var ngsi_connection = null;

    function init() {
        MashupPlatform.wiring.registerCallback('toBeSent', publishMsg);
        MashupPlatform.prefs.registerCallback(function(new_values) {
            if ('chatroom' in new_values) {
                subscribeChatRoom();
            }
        });

        subscribeChatRoom();
    }


    function publishMsg(event_data) {
    }

    function subscribeChatRoom() {
    }

    function receiveMessage(data){
        for(var msg in data.elements){
            MashupPlatform.wiring.pushEvent('toBeReceived', JSON.stringify(data.elements[msg]));
        }
    }

    init();

})();

Presenter Notes

基本的な NGSI チャット・オペレータ

NGSI コネクション

まず、config.xml ファイル内で NGSI を必須機能として宣言する必要があります :

    <requirements>
        <feature name="NGSI"/>
    </requirements>

NGSI 接続はそれを介してリクエストを行うために安定させる必要があります。 WireCloud にログオンしたユーザからの FIWARE トークンを使用して認証しています。 それを保持し、他の関数からアクセスするためのグローバル (クロージャ) 変数を宣言しました。

ngsi_connection = new NGSI.Connection(MashupPlatform.prefs.get('ngsi_server'), {
    use_user_fiware_token: true,
    ngsi_proxy_url: MashupPlatform.prefs.get('ngsi_proxy')
});

Presenter Notes

基本的な NGSI チャット・オペレータ

NGSI パブリケーション

新しいエンティティを作成したり、既存のエンティティを変更するには、接続の機能 addAttributes() が使用されます。チャット・アプリケーションの場合は、hashmsg 属性を使用して、ワイヤリングによって送信されるイベントとまったく 同じように、クラス ChatMessage の新しいインスタンスが作成されます。 詳細情報は、 WireCloud ドキュメントの NGSI API 、または WireCloud を使った Orion Context Broker チュートリアル にあります。

Presenter Notes

基本的な NGSI チャット・オペレータ

NGSI パブリケーション

作成するエンティティはこのようなものです :

[{
    entity: {id: MashupPlatform.prefs.get('chatroom') +  now.getTime() + msg.hash,
             type: 'ChatMessage'},
    attributes: [
        {
            type: 'string',
            name: 'hash',
            contextValue: msg.hash
        },
        {
            type: 'string',
            name: 'msg',
            contextValue: msg.msg
        }]
}]

Presenter Notes

基本的な NGSI チャット・オペレータ

NGSI パブリケーション

完全な publishMsg() の定義は次のようになります :

function publishMsg(event_data) {
    var now = new Date();
    var msg = JSON.parse(event_data);
    ngsi_connection.addAttributes([{
        entity: {id: MashupPlatform.prefs.get('chatroom') +  now.getTime() + msg.hash,
                 type: 'ChatMessage'},
        attributes: [
            {
                type: 'string',
                name: 'hash',
                contextValue: msg.hash
            },
            {
                type: 'string',
                name: 'msg',
                contextValue: msg.msg
            }]
    }]);
}

エンティティの ID は、固定部分 (チャットルームを示す設定) に加えて、 タイムスタンプとユーザ作成のハッシュを使用して作成されています。

Presenter Notes

基本的な NGSI チャット・オペレータ

NGSI サブスクリプション

このオペレータは、ChatMessageID がチャット・ルームで始まるすべてのタイプの インスタンスの変更 (作成は変更の一種です) を受け取ります。以前に (chatroom 変数に格納された) サブスクリプションを作成したことがある場合、 それをキャンセルします。

サブスクリプション自体が createSubscription() メソッドを呼び出して作成されます。これはいくつかのパラメータ (監視するエンティティの ID、あなたが興味を持っている属性のリスト、 サブスクリプションの期間など) を必要とします、 次のスライドでこのシナリオのための使用例を示します。

Presenter Notes

基本的な NGSI チャット・オペレータ

NGSI サブスクリプション

function subscribeChatRoom() {
    if (chatroom != null) {
        NGSI.cancelSubscription(chatroom);
    }

    var entityIdList = [
        {type: 'ChatMessage', id: MashupPlatform.prefs.get('chatroom') + '.*', isPattern: true}
    ];
    var attributeList = null;
    var duration = 'PT30M';
    var throttling = null;
    var notifyConditions = [{
        type: 'ONCHANGE',
        condValues: ['hash', 'msg']
    }];
    var options = {
        flat: true,
        onNotify: receiveMessage,
        onSuccess: function (data) {
            chatroom = data.subscriptionId;
        }
    };
    ngsi_connection.createSubscription(entityIdList, attributeList, duration, throttling, notifyConditions, options);
}

Presenter Notes

基本的な NGSI チャット・オペレータ

NGSI のサブスクリプションを更新

サブスクリプション期間は30分に設定されており、それより前に更新、またはページの リロードをする必要があります。サブスクリプションを更新する方法は、 このチュートリアルの将来のバージョンで示される予定です。それまでの間、 これ行う方法の一般的なチュートリアルについては WierCloud を使った Orion Context Broker チュートリアル をご覧ください。

Presenter Notes

Thanks!

Presenter Notes