目次


IoT を自宅に導入する: 自動車と自宅をつなげる

IBM Watson IoT Platform と Raspberry Pi、Bluetooth デバイス、プログラマブル電源タップを使って、帰宅途中の自動車が自宅に近づくと、電灯などの電化製品の電源をオンにする IoT を構築する

Comments

IoT 分野で最近盛んに話題になっているのは、ネットワーク接続された自動車やスマート・ホームです。詳しく調べてみると、ネットワーク接続された自動車とスマート・ホームは、それぞれのサイロに存在しているように思えます。スマート・ホームの住人は自分の携帯電話を使って電灯などの電化製品の電源をオンにすることができます。ですが、その手段を自動車に変えてはならない理由はありません。帰宅途中の自動車がスマート・ホームに近づくと、電源がオンになるという仕組みです。

このチュートリアルでは、IBM Bluemix と Node-RED を使用して自動車とスマート・ホームとをつなげ、電灯をつけたりエアコンを調節したりするなど、自動車という手段で家庭用電化製品を自動的にアクティベートする方法を説明します。

ここで説明する方法では、Raspberry Pi を使用してスマート・ホーム内の Bluetooth デバイスの信号強度を検知し、その情報を Watson IoT Platform に送信します。そして送信された信号強度に基づいて、Bluetooth デバイスを搭載した電化製品の電源をオンにします。また、自動車をスマート・ホームにつなげられるよう、GPS を利用して自動車を追跡し、スマート・ホームの周りをジオフェンスで囲みます。

この IoT アプリケーションを作成するために必要なもの

この実践的チュートリアルは、私が直前に、とりあえず自宅にあった機器を使用して行った概念実証 (PoC) に基づいています。皆さんは、これらのデバイスと同じものを使用することも、特定の目的に必要となるデバイスを代わりに使用することもできます。

私と同じようにこの IoT アプリを作成するには、以下のデバイス、アカウント、スキルが必要です。

  • USB Bluetooth ドングル付きの Raspberry Pi など、Bluetooth デバイスを搭載した Linux システム。C-Compiler が構成された Linux デバイスを使用することもできますが、デバイス・ゲートウェイとして毎日 24 時間ひっきりなしにコンピューターを実行していたい人はいないでしょう。
  • PC からオンにできる電源出力。私が使用したのは Gembird Silver Shield (プログラマブル電源タップ) ですが、皆さんの場合、これよりも適したブランドが他にあるかもしれません。
  • C プログラミング言語と、Linux システム (Linux ベースの Fedora オープンソース・オペレーティング・システムなど) 内での C 開発の知識。
  • IBM Bluemix アカウント(このリンク先のページでフリートライアルをリクエストできます。あるいは、developerWorks Premium に加入すると、12 ヶ月間の IBM Bluemix サブスクリプションと、Bluemix 上で利用できる 240 US ドル相当のクラウド・クレジットが提供されることをご存知でしたか?)
  • Bluemix の知識。カタログをブラウズして、Bluemix サービスをどのようにしてインスタンス化するのかを把握している必要があります。
  • MQTT の知識。特に、Eclipse Mosquitto ライブラリーの知識が必要です。Mosquitto は、MQTT プロトコルを実装するオープンソース・メッセージ・ブローカーで、主要な Linux ディストリビューションのすべてに含まれています。Linux プラットフォームのパッケージ管理ツールを使用して Mosquitto を検索し、使用するデバイスにそのパッケージをインストールしてください。
  • Node-RED の知識。Node-RED 内でノードをどのようにして使用するのか、Node-RED 内でどのようにしてメッセージを処理するのかを理解している必要があります。Node-RED は JavaScript のフロントエンドなので、JavaScript の経験も必要です。このリンク先の Node-RED Web サイトに用意されている入門資料を参考に、Node-RED について理解してください。

コードを入手するアプリを実行する

 

サンプル IoT アプリのアーキテクチャー

図 1 に、Bluetooth 信号の強度を受信するサンプル IoT アプリケーションの初期段階でのアーキテクチャーを示します。

図 1.サンプル IoT アプリケーションとデバイスのアーキテクチャーを示す図

図 1 に示されている丸で囲んだ番号の順に、IoT アプリケーションを作成していきます。

  1. IBM Bluemix 内で、Internet of Things Platform Starter を使用してアプリを作成します。作成するアプリは、最終的にはデバイスから受信したセンサー・データを読み取り、データをデバイスに送信するためのものです。データを送信してくる任意のデバイスからアプリを保護するために、各デバイスが API トークンを使用して自身を認証する必要があります。同様に、送信されてくるデバイス・データをアプリで読み取って処理するには、API トークンを使用して自身を認証する必要があります。
  2. Raspberry Pi デバイス上に、Bluetooth 信号の強度を読み取って、その値を継続的に IBM Watson IoT Pplatform に送信する MQTT クライアントを作成します。
  3. 住宅内の電灯とエアコンの電源をオンにするために、データを処理してプログラマブル電源タップに送信するコマンドを生成する Node-RED アプリを作成します。

この初期バージョンの IoT アプリの実装を完了した後、自動車の GPS 座標を考慮に入れるにはどのようにしてアプリを拡張するのかを説明します。また、GPS 制御機能に対してジオフェンスを定義する際や Bluetooth 近接センサーの感度を設定する際に使用するダッシュボードも開発します。

それでは、手順を開始しましょう。

1

IoT アプリを作成し、Raspberry Pi を Watson IoT Platform に接続する

まずは、Raspberry Pi を Watson IoT Platform に接続しましょう。

1a

Bluemix 内で IoT アプリを作成する

  1. Bluemix アカウントにログインします。
  2. Internet of Things Platform Starter ボイラープレートを使用して新規アプリを作成します。アプリには好きな名前を付けて構いません。このチュートリアルでは、「dw-example-iot」という名前にします。アプリケーションが起動されるまでに、多少時間がかかることもあります。
  3. 左側のナビゲーション・ペイン内で概要のリンクをクリックし、サービスがデプロイされるまで待ちます。
  4. 「ADD A SERVICE OR API (サービスまたは API の追加)」をクリックします。
  5. Internet of Things Platform サービスを見つけて、「CREATE (作成)」をクリックします。
1b

Raspberry Pi を Internet of Things Platform サービスに登録して認証トークンと許可トークンを識別する

Watson IoT Platform にデータを送信するには、使用するデバイスを Internet of Things Platform サービスに登録する必要があります。このチュートリアルでゲートウェイ・デバイスとして使用するのは Raspberry Pi です。デバイスを登録すると、認証トークンが生成されます。デバイスがこの認証トークンを使用することで、データを Watson IoT Platform に送信することが許可されます。

デバイスを一意に識別するためには、デバイスにクライアント ID が必要です。クライアント ID は、定義されている以下のフォーマットで作成されます。ここで、「typeid」はデバイスの目的を特定する文字列、「device-id」はデバイスの固有 ID です。
d:<organization>:<typeid>:<device-id>

使用する Raspberry Pi デバイス固有の MAC アドレスを識別するには、デバイス上で以下のコマンドを発行します。このコマンドによって返された MAC アドレスを、デバイスの固有 ID として使用できます。
ip add show|grep -A1 '^[0-9]:'

コマンド出力内で、「eth0」、「em1」、または「enp1s0」のような名前のインターフェースを探します。インターフェースの名前は Linux ディストリビューションによって異なりますが、インターフェース名の後に続く行に「link/ether」として MAC アドレスが示されています。

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
--
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 12597 qdisc pfifo_fast state UP….
link/ether b8:72:be:f2:7a:a8 brd ff:ff:ff:ff:ff:ff

次の手順に従って、デバイスを登録します。

  1. Bluemix アプリケーション・ダッシュボード内で、Internet of Things Platform サービスをクリックします。
  2. 左側の列内で、下部にある「Launch dashboard (ダッシュボードを起動)」をクリックします。ブラウザーの新しいウィンドウまたはタブが開きます。ダッシュボードの最上部に、自分の組織 ID が表示されます。
  3. 組織 ID の下にある「Devices (デバイス)」セクション内で、「Add Device (デバイスの追加)」をクリックします。
  4. デバイス・タイプ (typeid) として「proximity」を指定し、デバイス ID (device-id) としてイーサネット・デバイスの MAC アドレス (コロンを除く) を指定します。
  5. 「Continue (続行)」をクリックします。
  6. 次のページに、デバイスの「Authentication Token (認証トークン)」をはじめとする重要な資格情報が表示されるので、これらの資格情報をメモしてください。
1c

接続をテストする

デバイスが Watson IoT Platform に登録されたので、次は認証トークンを使用して Raspberry Pi からテスト・メッセージを送信します。メッセージを送信する際に、Mosquitto MQTT ライブラリーを利用しましょう。例えば、Raspberry Pi にログインし、組織固有の値とデバイス ID を指定した以下の Mosquitto コマンドを発行します。

mosquitto_pub -h e62whi.messaging.internetofthings.ibmcloud.com \
-i d:e62whi:proximity:b872bef27aa8 \
-u use-token-auth -P '<your device credentials here>' \
-t /iot/x -m '{"d":"hello iot"}'

Watson IoT Platform のダッシュボード内で、デバイスのセンサー情報に「hello iot」というメッセージが表示されていることを確認します。

Watson IoT Platform ダッシュボードを表示している間に、Node-RED アプリケーションに、IoT アプリに送信されたデバイス・データの使用が許可されることを確認しましょう。それには、認証トークンを使用するのではなく、API 許可トークンを使用する必要があります。このアプリからのデータを使用する許可を他のアプリに与えるには、以下の手順に従います。

  1. Watson IoT Platform ダッシュボード内で、「Access (アクセス)」「API Keys (API キー)」の順にクリックします。
  2. 「Generate API Key (API キーの生成)」をクリックします。
  3. 次のページに API 資格情報が表示されるので、これらの情報をメモします。特に「Authentication Token (認証トークン)」の値は重要です。
2

Raspberry Pi 上に Bluetooth 信号の強度を読み取る MQTT クライアントを作成する

C プログラムとして作成するこの MQTT クライアントは、Bluetooth 信号の強度を読み取り、その値を Bluemix 上の IoT アプリケーションに送信するだけでなく、IoT アプリケーションからコマンドを受信して、そのコマンドを実行するスクリプトを呼び出します。

2a

Bluetooth デバイスの MAC アドレスを判別する

デバイス・クライアントが Bluetooth デバイスに接続するには、デバイスの MAC アドレスを使用する必要があります。Bluetooth デバイスの MAC アドレスを判別するには、デバイス (この例の場合は Raspberry Pi) 上で以下のコマンドを発行します。これにより、以下のような結果が出力されます。

# bluetoothctl
[NEW] Controller 00:15:83:07:CC:97 traumcloud.enet [default]

[Bluetooth]# power on
Changing power on succeeded
[CHG] Controller 00:15:83:07:CC:97 Powered: yes

[Bluetooth]# scan on
Discovery started
[CHG] Controller 00:15:83:07:CC:97 Discovering: yes
[NEW] Device 3C:77:E6:EF:57:F5 3C-77-E6-EF-57-F5
[NEW] Device 00:0A:3A:2B:C6:ED MSI FT200
[CHG] Device 00:0A:3A:2B:C6:ED RSSI: -79
[CHG] Device 00:0A:3A:2B:C6:ED RSSI: -88

[Bluetooth]# agent on
Agent registered

[Bluetooth]# pair 00:0A:3A:2B:C6:ED
Attempting to pair with 00:0A:3A:2B:C6:ED
Request PIN code
[agent] Enter PIN code: 1234
[DEL] Device 3C:77:E6:EF:57:F5 3C-77-E6-EF-57-F5
[CHG] Device 00:0A:3A:2B:C6:ED Connected: yes
[CHG] Device 00:0A:3A:2B:C6:ED UUIDs:
        00001108-0000-1000-8000-00805f9b34fb
        0000111e-0000-1000-8000-00805f9b34fb
[CHG] Device 00:0A:3A:2B:C6:ED Paired: yes
Pairing successful

[Bluetooth]#exit

私が調べているのは「MSI FT200 headset」の MAC アドレスなので、この出力例から、その MAC アドレスが「00:0A:3A:2B:C6:ED」であることがわかります。該当するデバイスの MAC アドレスをメモしてください。

2b

MQTT のコアをコーディングする

Mosquitto ライブラリーが初期化された後、MQTT クライアント・プログラムは対象とするイベントのコールバックを設定し、Bluemix 内の Internet of Things Platform サービスに接続します。以下の初期化コードは基本的に、Mosquitto Web サイトのサンプル・コードに従っています。

        mqtt = mosquitto_new(cfg.deviceid, 1, NULL); 
        if(!mqtt){
                tprintf("Cannot Initialize MQTT library\n");
                mosquitto_lib_cleanup();
                return 1;
        }
        mosquitto_connect_callback_set(mqtt, bt_connect_callback);
        mosquitto_disconnect_callback_set(mqtt, bt_disconnect_callback);

上記のコードの後に、MQTT イベントに対する Mosquitto コールバックを追加します。

        mosquitto_log_callback_set(mqtt, bt_log_callback);
        mosquitto_message_callback_set(mqtt, bt_message_callback);
        mosquitto_subscribe_callback_set(mqtt, bt_subscribe_callback);
         dprintf("now setting username and password to %s/*************\n", cfg.username);
        sts=mosquitto_username_pw_set(mqtt, cfg.username, cfg.password);
        if(sts) {
                tprintf("Error setting username/password\n");
                return sts;
        }
        dprintf("now connection using host=%s port=%d\n", cfg.host, cfg.port);
        sts = mosquitto_connect_bind(mqtt, cfg.host, cfg.port, 60, NULL);
        if(sts) {
                tprintf("Error connecting to %s:%d as %s\n", HOST, PORT, IDFMT);
                return sts;

このプログラムは、接続コールバックによって適切な接続が報告されるというイベントにサブスクライブします。

void bt_connect_callback(struct mosquitto *mqtt, void *obj, int result) {
         char buf[1024];
        dprintf("conn cb %d '%s'\n", result, mosquitto_connack_string(result));
        is_connected=(result==0?CONN_OK:CONN_ERR);
        if (is_connected==CONN_OK) {
                mosquitto_subscribe(mqtt, NULL, cfg.subscription, 0);
        }
        sprintf(buf, PAYLOAD, -100, -100); // simulate a very far away beacon
        mosquitto_publish(mqtt, NULL, TOPIC, strlen(buf), buf, 0, false);
}

メイン・プログラムをループ処理で実行して、定期的に Bluetooth 信号の強度を送信するようにします。

while (is_connected != CONN_ERR) {
                if (is_connected == CONN_OK) publish_bt(mqtt);
                else dprintf("waiting for connection to come up\n", "");
                sleep(cfg.sleep);
        }
2c

外部スクリプトを呼び出す

Mosquitto ライブラリーは受信したコマンドを処理して、該当するコールバック関数を呼び出します。この例では、外部スクリプトを呼び出して、そのスクリプトで実際の処理を行います。外部スクリプトを使用すると、さまざまなアクチュエーターを使って柔軟にアプリケーションを制御できます。

void bt_message_callback(struct mosquitto *mqtt, void *udata, const struct mosquitto_message *message) {
        dprintf("msg cb topic='%s' payload='%s'\n", message->topic, message->payload);
/*
 * A execute script btclient.d/command.sh
 */
         int pid,sts;
        pid = fork();
        switch (pid) {
        case 0:         // child, execute shell script
                setenv("TOPIC", message->topic, 1);
                setenv("PAYLOAD", message->payload, 1);
                sts=execl("btclient.d/mqtt-command.sh", "mqtt-command", (const char*)NULL);
                tprintf("something went wrong with execl(), error='%s'\n", strerror(errno));
         break;
        case -1:        // error
                tprintf("something went wrong with fork(), error='%s'\n", strerror(errno));
        break;
        default:        // parent
                wait(&sts);
        break;
        }
}

スクリプトを使用することで、使用する特定のハードウェアやスマート・デバイスに合わせて簡単に MQTT クライアントを改造できるようになります。私が使っている Gembird Silver Shield プログラマブル電源タップでは、USB と sispmctl という Linux ユーティリティー (Fedora Linux にパッケージとして用意されています) を使用して、4 つの電源ソケットの個々の切り替えを制御できます。

#!/bin/bash
if [ "$TOPIC" == "iot-2/cmd/switch/fmt/text" ];then
        [ "$PAYLOAD" == "on" ] && arg="-o4"
        [ "$PAYLOAD" == "off" ] && arg="-f4"
        [ "$arg" != "" ] && sispmctl $arg
fi

433 MHz のトランシーバーを使用してワイヤレス電源ソケットをオンにする場合は、pilight フレームワークを使用しました。pilight フレームワークは、Raspberry Pi 上のホーム自動化フレームワークです。特定のニーズを満たす電源ソケットとプロジェクトを調査してください。

2d

MQTT クライアント構成ファイルに変更を加える

MQTT クライアントは起動時に構成ファイルを読み取ります。構成ファイルの名前は実行可能ファイルと同じ名前ですが、拡張子 .cfg が付いています。この別個の構成ファイルを使用することで、実行可能ファイルの名前を変えるだけで異なるインスタンスを実行できます。例えば、otherclient が起動された後、MQTT クライアントはその構成ファイルとして otherclient.cfg を読み取るといった具合です。

構成ファイルによって、以下の項目を定義します。

  • btmac: (Linux システムの組み込みデバイスではなく) 信号の強度を測定する Bluetooth デバイスの MAC アドレスを使用します。
  • subscription: クライアントがサブスクライブする必要があるトピックを使用します。この例でそれに該当するのは、iot-2/cmd/switch/fmt/+ です。
  • host: Internet of Things Platform サービス・インスタンスのホスト名。「hello iot」メッセージを送信したときに使用した名前を使用します。
  • password: デバイス認証トークンのパスワード。デバイスを登録したときにメモしたパスワードを使用します。
  • username: ユーザー名は、リテラル文字列「use-token-auth」です。
  • typeid: typeid は、デバイスを登録したときに使用したデバイス・タイプです。この例の場合、「proximity」を使用しました。
  • organization: 自分の組織 ID を使用します。
3

Bluetooth 信号を検知して電化製品の電源をオンにする Node-RED アプリを作成する

MQTT は、Bluemix 内の Internet of Things Platform サービスに一定の間隔で Bluetooth 信号の強度を送信します。Bluemix 内には、この信号強度の値を処理するアプリケーションを作成する必要があります。そのアプリを作成する環境として、このチュートリアルでは Node-RED を使用します。

3a

Node-RED アプリを作成してデバイスを接続する

最初に、デバイスを接続して、デバイスがメッセージを受信することを確認します。

  1. Bluemix IoT アプリ内で、左側のナビゲーション・ペインにある「start coding (コーディングを開始)」リンクをクリックします。
  2. 画面の上部に示される、実行中アプリの URL を見つけて、その URL をクリックします。
  3. 大きな赤いボタンをクリックして Node-RED フロー・エディターを開きます。
  4. フロー・エディターにはサンプル・アプリケーションが表示されています。フロー内のすべての要素を選択して削除します。
  5. ibmiot」入力ノードをワークスペースにドラッグし、ノードを構成するためにダブルクリックします。「API Token (API トークン)」フィールドに、前に作成した API 認証トークンを入力し、デバイス・データにアクセスできるようにします (以下の図を参照)。
  6. 「device type (デバイス・タイプ)」、「device ID (デバイス ID)」、「event (イベント)」、「format (フォーマット)」にはいずれも「All (すべて)」を選択します。
  7. デバイスをテストするために、Linux システム上でデバイス・クライアントを起動します。メッセージが Watson IoT Platform に送信されることを確認します。
    [root@traumcloud btclient]# ./dwclient
    [2015-08-18 17:16:39] trying to use ./dwclient.cfg for configuration
    [2015-08-18 17:16:39] got option 'btmac' with arg 00:0A:3A:2B:C6:ED
    [2015-08-18 17:16:39] got option 'subscription' with arg iot-2/cmd/switch/fmt/+
    [2015-08-18 17:16:39] got option 'host' with arg e62whi.messaging.internetofthings.ibmcloud.com
    [2015-08-18 17:16:39] got option 'password' with arg R3!1sFY(846HRCC0P6
    [2015-08-18 17:16:39] got option 'username' with arg use-token-auth
    [2015-08-18 17:16:39] got option 'typeid' with arg proximity
    [2015-08-18 17:16:39] got option 'organisation' with arg e62whi
    [2015-08-18 17:16:39] got MAC address of this machine as 'b827eb2fa78a'@  eth0
    [2015-08-18 17:16:39] now setting username and password to use-token-auth/*************
    [2015-08-18 17:16:39] now connection using host=e62whi.messaging.internetofthings.ibmcloud.com port=1883
    [2015-08-18 17:16:39] log cb: 'Client d:e62whi:proximity:b827eb2fa78a sending CONNECT'
    [2015-08-18 17:16:40] log cb: 'Client d:e62whi:proximity:b827eb2fa78a received CONNACK'
    [2015-08-18 17:16:40] conn cb 0 'Connection Accepted.'
    [2015-08-18 17:16:40] log cb: 'Client d:e62whi:proximity:b827eb2fa78a sending SUBSCRIBE (Mid: 1, Topic: iot-2/cmd/switch/fmt/+, QoS: 0)'
    [2015-08-18 17:16:40] log cb: 'Client d:e62whi:proximity:b827eb2fa78a sending PUBLISH (d0, q0, r0, m2, 'iot-2/evt/status/fmt/json', ... (31 bytes))'
    [2015-08-18 17:16:40] log cb: 'Client d:e62whi:proximity:b827eb2fa78a received SUBACK'
    [2015-08-18 17:16:40] sub cb 1 subscriptions
    [2015-08-18 17:16:41] BT MQTT msg '{ "d": {"lq":235,"rssi":-13}}'
    [2015-08-18 17:16:41] log cb: 'Client d:e62whi:proximity:b827eb2fa78a sending PUBLISH (d0, q0, r0, m3, 'iot-2/evt/status/fmt/json', ... (29 bytes))'
    [2015-08-18 17:16:46] BT MQTT msg '{ "d": {"lq":250,"rssi":-13}}'
    [2015-08-18 17:16:46] log cb: 'Client d:e62whi:proximity:b827eb2fa78a sending PUBLISH (d0, q0, r0, m4, 'iot-2/evt/status/fmt/json', ... (29 bytes))'
  8. debug」出力ノードをワークスペースにドラッグして、このノードを「ibmiot」ノードに接続します。
  9. 「Deploy (デプロイ)」をクリックします。
  10. 右側の「Debug (デバッグ)」タブをクリックして、デバッグ・メッセージが受信されていることを確認します。
  11. Bluetooth デバイスを近づけたり離したりして、RSSI (受信信号強度インジケーター) の最小値/最大値が変わることを確認します。
3b

Bluetooth デバイス・データを処理する Node-RED アプリを作成する

デバイスが接続されていることを確認したので、Node-RED アプリケーションの作成を開始できます。

  1. まずは、初期化関数から取り掛かります。「Inject」ノード、「function」ノード、「debug」出力ノードをワークスペースにドラッグし、これらのノードをこの順で接続します。
  2. Inject」ノードを構成します。「payload (ペイロード)」をブランクにして、「inject once at start (起動時に一度注入)」にチェック・マークを付け、ノードに意味のある名前 (例えば、「AppSetup」) を指定します。
  3. 以下のコードを使用して「function」ノードを構成し、意味のある名前を付けます。「rssimin」に指定する値は、Bluetooth デバイス用に検出してメモした最小値と最大値の平均をとった値にしてください。
    	// bluetooth related
    context.global.bttime=0;
    context.global.rssimin=-32;
    context.global.rssi=0;
    context.global.inBeacon=false;
    	
    // Timer related
    context.global.lastCmd="";
    context.global.nextSwitch=0;
    context.global.delay=30*1000; // 30 secs 
    
    	// will be used later with gps
    	context.global.gpstime=0;
    	context.global.gps={lat: 0.0, lng:0.0};
    	context.global.inFence=true;
    	msg.payload="App initialized";
    	return msg;
  4. msg.payload」を出力するように「Debug」ノードを構成し、意味のある名前を付けます。
  5. コードをデプロイします。「Debug (デバッグ)」タブに、「App initialized (アプリケーションの初期化完了)」というメッセージが表示されることを確認します。
  6. inject」ノード、「ibmiot」入力ノード、2 つの「function」ノード、「ibmiot」出力ノード、「debug」ノードをワークスペースにドラッグします。
  7. 以下のコードを使用して、最初の「function」ノードを構成します。
     	context.global.rssi=msg.payload.d.rssi
    	context.global.inBeacon=context.global.rssi>context.global.rssimin;
    	return msg;
  8. 2 番目の「function」ノードの構成には、以下のコードを使用します。
    	//
    // determine when to send a switch command
    // A command is sent when a grace period has 
    // expired since last switch (to protect the
    // appliance) and if the state of the appliance 
    // is to be changed
    now = Date.now();
    dbg={ payload:""};
    var cmd=(context.global.inBeacon &&
     context.globalinFence)?"on":"off";
    if (now > context.global.nextSwitch && 
     context.global.lastCmd != cmd) {
     // we need to switch now
     context.global.nextSwitch+=now+context.global.delay;
     context.global.lastCmd=cmd;
     msg.payload=cmd;
     dbg.payload="switch appliance '"+cmd+"'";
    } else {
     msg=null
     dbg.payload="not switching appliance";
    }
    return [ msg, dbg ];
  9. ibmiot」ノードを、以下のスクリーンショットに示すように構成します。
  10. 最後に、以下に示すようにノードを接続します。
3c

Node-RED アプリをテストする

  1. アプリをデプロイします。「App initialized (アプリケーションの初期化完了)」というメッセージが表示されることを確認します。
  2. デバイスがまだ接続されていない場合、フローをテストするために、「timestamp」ノードをクリックしてメッセージを注入します。デバイスが接続されている場合は、定期的に「not switching appliance (電化製品の電源オン/オフは切り替えられていません)」というメッセージが表示されます。
  3. Bluetooth デバイスをLinux システムに対してゆっくりと近づけたり遠ざけたりして、この動きに合わせて電化製品の電源オン/オフが試行されていることをデバッグ・メッセージで確認します。同時に、Raspberry Pi 上で実行中のクライアント・プログラムに on コマンドまたは off コマンドが到達していること、ファンや電灯、あるいはエアコン (A/C) の電源をオンにするように構成されているスクリプトが呼び出されていることも確認できるはずです。速度制限として、切り替えは 30 秒あたり 1 回に制限されていますが、テストの際は、context.global.delay パラメーターの値を小さくしても構いません。
4

Node-RED アプリに GPS データを受け入れて処理するためのフローを追加する

これまでの作業で、Bluetooth デバイスが近づくと電化製品の電源をオンにするアプリを作成しました。次は、GPS デバイスが提供する特定のジオロケーション情報を使用して、電化製品の電源をオンにするタイミングを判断するように、このアプリを拡張します。

最近の GPS はさまざまな通信プロトコルを使用していますが、このチュートリアルおよびサンプル・アプリでは、GPS が緯度と経度のペアを HTTP リクエストのメッセージ・ペイロードとして送信することを前提とします。

4a

GPS デバイスの HTTP エンドポイントを作成する

Node-RED フロー・エディター内で、「HTTP-input」ノードをワークスペースにドラッグします。ノードをダブルクリックし、以下の値を使用してノードを構成します。

  • Method (メソッド): POST
  • URL: /gps
  • Name (名前): GPS Input [POST] /gps

この「HTTP」ノードは、URL http://dwexample-iot.mybluemix.net/gps 上で POST リクエストを受け入れます。POST データは、Node-RED フロー内でメッセージ・オブジェクトとして使用できます。GPS デバイスから送信された緯度と経度の値は、ジオフェンスに対し、さらに処理されます。

ジオロケーションによる電化製品の制御は、特定のロケーションに束縛されません。通常、電化製品の制御が行われるのは、定義されたジオフェンスへの出入りがあったときです。このアプリケーション内でのジオフェンスは、以下のように JSON オブジェクトとしての緯度と経度のペアからなる配列として表現されます。

[
    {"lat":43.7074340290373,"lng":7.28219747543335},
	…
	…	
    {"lat":43.705196002070636,"lng":7.284321784973145},
    {"lat":43.706995349373884,"lng":7.284793853759766}
]
4b

Cloudant データベースからジオフェンスを取得する

緯度と経度のペアの配列は、Cloudant データベースに保管されます。Cloudant データベースは、アプリを作成するときに使用した Internet of Things Platform Starter に含まれていますが、皆さんのアプリに Cloudant データベースが含まれていない場合は、Bluemix カタログを表示して、そこに用意されている Cloudant NoSQL DB サービスを見つけてサービス・インスタンスを作成してください。

GPS 座標が含まれるメッセージを受信した時点で、アプリは Cloudant データベースからジオフェンス定義を取得し、その定義に基づいて、送信されたロケーションがジオフェンスの内側にあるのか外側にあるのかを判別しなければなりません。データベース・ノードはメッセージのペイロード要素をオーバーライドするため、HTTP リクエスト本文を一時的に保存する必要があります。この HTTP リクエストの一時ストアとしては、Node-RED のグローバル属性を使用することにします。

Node-RED フロー・エディター内で、「function」ノードを追加し、そのノードに以下の JavaScript コードを追加します。

context.global.gps=msg.payload;
context.global.gpstime=Date.now();
msg.save=msg.payload;
msg.payload="fence";
return msg;

実際のデータベース・クエリーは、パレットのストレージ・セクションにある Cloudant ノードによって行われます。左側に小さい雲が示されたノードをドラッグします。これが、Cloudant の「query」ノードです。

以下の値を使用してノードを構成します。

  • Service (サービス): <アプリケーション名>
  • Database (データベース): tsldemo
  • Search by (検索基準): _id
  • Name (名前): Retrieve Fence
4c

GPS 座標がジオフェンスの内側にあるのかどうかを判別する

Cloudant」ノードの出力は別の「function」ノードに取り込まれます。そのノードで、JavaScript スニペットにより GPS 座標がジオフェンスの内側にあるのか外側にあるのかを判別します。そのためのアルゴリズムは、GitHub 上のサブスタックにある、このリンク先の point-in-polygon リポジトリーから入手したものです。「function」ノードは、グローバル構造体のメンバーにインターフェースの状態を記録します。

function」ノードの出力は、以下のノードに取り込まれます。

  • 正しいステータスを GPS デバイスに返す「HTTP response」ノード
  • GPS の追跡に Bluetooth の測定を統合するノード

このノードが実装する関数は、「GPS がフェンスの内側にある場合、または自動車が Bluetooth センサーに十分近づいている場合、前回の切り替えが <n> 分以前に行われていないときに限って、A/C の電源をオンにします」。最後の条件を加えることで、自動車がジオフェンスの境界を運転している際に、アプリが頻繁に A/C 電源のオン/オフを切り替えることを防ぎます。以下に、この関数を実装するコードの一例を示します。

//
// determine when to send a switch command
// A command is sent when a grace period has 
// expired since last switch (to protect the
// appliance) and if the state of the appliance 
// is to be changed
now = Date.now();
var cmd=(context.global.inBeacon ||
 context.global.inFence)?"on":"off";
if (now > context.global.nextSwitch && 
 context.global.lastCmd != cmd) {
 // we need to switch now
 context.global.nextSwitch=now+context.global.delay;
 context.global.lastCmd=cmd;
 msg.payload=cmd;
 msg.format="text";
} else {
 msg=null
}
return msg;

最終的な Node-RED アプリケーションは図 2 に示すようなフローになります。薄いグレーのノードと濃いグレーのノードは、ステップ 1 から 4 で作成したものです。

図 2. 最終的な Node-RED アプリ
4d

ジオフェンスの関数を検証する

シミュレーションした GPS 座標を curl コマンドによって送信して、新しいジオフェンスの関数を簡単にテストしてみましょう。

  1. Bluemix ダッシュボード内で Cloudant DB サービスをクリックします。
  2. 「Launch (起動)」をクリックして、Cloudant データベースのダッシュボードを開きます。
  3. データベース・ダッシュボード内で、新しいドキュメントを挿入します。
    	"_id": "fence",
      "fence": "[{\"lat\":50.945,\"lng\":6.955},{\"lat\":50.946,\"lng\":6.957},{\"lat\":50.943,\"lng\":6.962},{\"lat\":50.940,\"lng\":6.962}]"
  4. 「Save (保存)」をクリックしてドキュメントを保存します。
  5. シミュレーションした 2 つの GPS 座標 (ジオフェンスの内側に位置する lat/lng のペアと、外側に位置する lat/lng のペア) を以下の curl コマンドを発行して (サンプル・アプリケーション名を指定して) 送信し、Node-RED フローをテストします。
    	curl -XPOST -d 'lat=1&lng=26' dwexample-iot.mybluemix.net/gps
    	{
    	  "bttime": 0,
    	  "rssimin": -32,
    	  "rssi": 0,
    	  "inBeacon": false,
    	  "lastCmd": "on",
    	  "nextSwitch": 1447771815039,
    	  "delay": 5000,
    	  "gpstime": 1447771815841,
    	  "gps": {
    	    "lat": "1",
    	    "lng": "2"
    	  },
    	  "inFence": false,
    	}

    Node-RED フロー・エディターのデバッグ・タブに表示されるメッセージを確認します。

    [root@traumcloud btclient]# ./dwclient
    trying to use ./dwclient.cfg for configuration
    got option 'btmac' with arg 00:0A:3A:2B:C6:ED
    got option 'subscription' with arg iot-2/cmd/switch/fmt/+
    [2015-11-17 18:42:25] got option 'host' with arg e62whi.messaging.internetofthings.ibmcloud.com
    got option 'password' with arg R3!1sFY(846HRCC0P6
    got option 'username' with arg use-token-auth
    got option 'typeid' with arg proximity
    got option 'organisation' with arg e62whi
    got MAC address of this machine as 'b827eb2fa78a'@  eth0
    now setting username and password
    log cb:received PUBLISH (d0, q0, r0, m0, '...'
    msg cb topic='iot-2/cmd/switch/fmt/text' payload='on'
    set state of switch2 to on
    log cb: 'Client received PUBLISH (d0, q0, r0, m0, '...'))'
    msg cb topic='iot-2/cmd/switch/fmt/text' payload='off'
    set state of switch2 to off
5

GPS ジオフェンスの編集とビーコンのしきい値設定に使用するダッシュボードを追加する

これまで、2 通りの方法で自動車のロケーションを取得することによって、A/C を制御しました。具体的には、以下のいずれかの方法です。

  • 駐車場や車庫にある Bluetooth ビーコンを検知する
  • GPS 座標によって自動車を追跡する

現時点で、このサンプル・アプリには、これら 2 つの近接デバイスを管理する方法がまだありません。ビーコンのしきい値を設定するとともに、ジオフェンスの定義をより実際的なものにする必要があります。これらのデバイスを管理するために、これから管理 UI として Web ページを追加し、現在の動作値を返したり、新しい値を設定したりするための新しいフローをバックエンド・アプリに追加します。図 3 を参照してください。

図 3. Bluetooth の感度および GPS の視覚化に対応するためのダッシュボード

図 4 のシーケンス図に、このダッシュボードを作成するために必要なコンポーネントと、コンポーネント間のやり取りを示します。ダッシュボードは、以下の使用例をサポートします。

  • GPS座標と Bluetooth 感度の継続的モニタリング
  • Bluetooth 感度の編集および変更
  • ジオフェンスの編集および変更

HTML ページとして実装されるこのダッシュボードでは、Ajax リクエストを使用してバックエンド・アプリケーションからデータを取得します。図 4 の左側に示されているこのダッシュボードのライフラインは、Node-RED 内でフローとして実装します。

図 4. Bluetooth の感度および GPS の視覚化に対応するためのダッシュボード
5a

ダッシュボード Web ページを作成する

このダッシュボードを作成するために必要なファイルは、GitHub 上にある、このリンク先の私の car-meets-home リポジトリーからダウンロードできます。ダウンロードしたこれらのファイルを、Bluemix IoT アプリにインポートしてください。

  1. Bluemix ダッシュボード内で、作成した IoT アプリケーションを選択して「Edit Code (コードの編集)」をクリックします。

    Bluemix DevOps サービスが開きます。アプリケーションの「Edit Code (コードの編集)」を初めてクリックする際には新しいプロジェクトが生成されるため、Bluemix DevOps サービスが開くまでに多少時間がかかります。

  2. 左側のナビゲーション・バー内で、public フォルダーを見つけます。public フォルダーを右クリックして「Import (インポート)」を選択します。
  3. 表示されるダイアログ内で、dash.html ファイルにナビゲートし、「Open (開く)」をクリックします。public フォルダー内に保管されている dash.html ファイルが表示されます。
  4. もう一度 public フォルダーを右クリックして「New (新規)」 > 「Folder (フォルダー)」の順に選択します。新しいフォルダーに「js」という名前を付けます。
  5. js フォルダーを右クリックし、dash.js ファイルをインポートします。
  6. css フォルダーを右クリックし、dash.css ファイルをインポートします。
  7. images フォルダーを右クリックし、.png 拡張子の付いたすべてのファイルをインポートします。

    以上のファイルがダッシュボード・アプリを構成します。アプリケーション・ルートの末尾に /dash.html を追加して使用すると (例えば、<自分の名前>.mybluemix.net/dash.html)、ダッシュボードを開くことができます。

5b

Ajax リクエストに対応する API をフローに追加する

ダッシュボードを機能させるには、Node-RED フローにいくつかの API を追加する必要があります。ダッシュボードは、/status に対する HTTP-GET リクエストを出すことによって、バックエンド・アプリケーションのステータスを取得します。同様に、/status に対する HTTP-POST リクエストを出すことによって、新しい rssimin 値 (感度) を送信します。ジオフェンス・データを取得するには /fence に対する GET を使用する一方、/fence に対する POST によってジオフェンス・データを保管します。

以下の手順に従って、フローを作成し、コードを関数に追加します。

  1. 以下の図に示すように、ステータスを取得して更新するためのフローを追加します。
  2. 以下のコードを「Add global as payload」という名前を付けたノードに追加します。
    msg.payload=context.global;
    msg.payload.jt=Date.now();
    return msg;
  3. Web ページに含まれる以下の JavaScript コードが、Bluetooth と GPS の値を取り、それらの値をテキスト形式で表示するとともに、グラフ上では Bluetooth の値を計器の値として、GPS 値を地図上の位置として表示します。このようにデータを表示する、このコードの中核となる行は以下のとおりです。
    	    //
    	    // get status and display methods
    	    //
    	    this.getData=function () {
    		 	$.ajax({url: "/status",
    		 	 	success: thiz.getDataOK,
    		 	 	error: thiz.getDataErr,
    		 	 	dataType: "json"
    		 	});
    		 	window.setTimeout(thiz.getData, 5000);
    	    };
    	    this.getDataOK=function (data) {
    		 	//console.dir(data);
    		 	if (olddata == null) olddata=data;
    	
    		 	car.setLatLng(L.latLng(data.gps.lat, data.gps.lng));
    		 	map.panTo(L.latLng(data.gps.lat, data.gps.lng));
    	
    		 	$('#bt-rssi').text(data.rssi+"/"+data.lq);
    		 	$('#bt-rssimin').text(data.rssimin);
    		 
    		 	$('#time').text(new Date().toLocaleString());
    		 	thiz.drawRssiMeter(data);
    		 	olddata=data;
    	
    	    };
    	    this.drawRssiMeter=function (data) {
    		 	var rssi=Math.floor(data.rssi||-50);
    		 	var rssimin=Math.floor(data.rssimin||-50);
    		 	var min = Math.min(rssimin, rssi);
    		 	var max = Math.max(rssimin, rssi);
    	
    		 	var rssiMeterData = new google.visualization.DataTable();
    	
    		 	rssiMeterData.addColumn('number', 'Rssi');
    		 	rssiMeterData.addColumn('number', 'lq');
    		 	rssiMeterData.addRows(2);
    		 	rssiMeterData.setCell(0, 0, rssi);
    	
    		 	rssiMeterOptions.min=min-15;
    	 	 	rssiMeterOptions.max=max+5;
    		 	 	 	 
    		 	rssiMeterOptions.greenFrom=rssimin;
    		 	rssiMeterOptions.yellowTo=rssimin;
    	  	 	// draw space from min to yellow to half yellow, half red
    		 	var step=Math.floor(Math.abs(rssimin-rssiMeterOptions.min)/2);
    		 	rssiMeterOptions.yellowFrom=rssimin-step;
    		 	rssiMeterOptions.redTo=rssimin-step;
    	
    		 	rssiMeterOptions.redFrom=Math.min(min,rssimin)-2*step;
    		 	 
    		 	rssiMeter.draw(rssiMeterData, rssiMeterOptions);
    	    };
  4. ダッシュボードには、データのポーリングの合間に変化した値を赤で表示するためのコード行も含まれます。

    「Enter new value for RSSI Min (RSSI の最小値を入力)」という名前のボタンは、RSSI の入力値を取り、そのデータを Node-RED API に送信します。

        this.getDataErr=function (xhr, sts, txt) {
    	    thiz.error("Ajax Error: sts='"+sts+"', txt='"+txt+"'");
        };
        //
        // update bluetooth sensitivity
        //
        this.setRssiVal=function() {
    	 	var url="/status";
    	 	$.ajax({url: url,
    	 	 	success: thiz.getDataOK,
    	 	 	error: thiz.getDataErr,
    	 	 	method: "POST",
    	 	 	data: {rssimin: $('#rssid-val-text').val().trim()},
    	 	 	dataType: "json"
    	 	 	});
        };
  5. Node-RED API は、RSS 値 (Bluetooth の感度) をグローバル変数構造体に設定します。
    if (msg.payload.rssimin) context.global.rssimin=msg.payload.rssimin;
    msg.payload=context.global;
    return msg;
  6. 同じようにして、切り替え処理の遅延時間に対応する UI 要素を追加し、それらの UI 要素を rssimin と同じようにフロー用に設定できます。

    ジオフェンス・データを取得するためのフローを、以下の図に示すように追加します。

        var storeFence=function() {
        	var ll=fence.getLatLngs();
    	 	var data={ fence: JSON.stringify(ll) };
    	 	if (fencers._id !== undefined) data._id=fencers._id;
     	 	if (fencers._rev !== undefined) data._rev=fencers._rev;
    	 	// upload to bluemix
    	 	$.ajax({
    	 	 	url: "/fence2",
    	 	 	data: data,
      	 	 	contenttype: "application/json",
    	 	 	method: "POST",
    	 	 	/**
    	 	 	 * @callback
    	 	 	 */
    	 	 	success: function( data ) {
    	 	 	 	$('#upload').show();
    	 	 	 	window.setTimeout(function() {
    	 	 	 	 	$('#upload').fadeOut(2000);
    	 	 	 	}, 2000);
    	 	 	 	loadFence(); // to update _rev
    	 	 	}
    	 	});
    	};
  7. ジオフェンスのロードは、2 つのメソッドとして実装します。一方は Node-RED API を非同期で呼び出すメソッド、もう一方はコールバック関数としてのメソッドです。ジオフェンスは、アプリケーションの起動時、またはユーザーが「Load (ロード)」ボタンを押した時点でロードされます。
    var loadFence=function() {
    	// load the fence definition from bluemix
    	//
    	$('#download').show();
    	$.ajax({
    	 	url: "/fence",
    	 	contenttype: "application/json",
    	 	method: "GET",
    	 	success: function( data ) {
    	 	 	$('#download').fadeOut(1000);
    	 	 	$('#received').fadeIn(1000);
    	 	 	window.setTimeout(function() {
    	 	 	 	$('#received').fadeOut(1000);
    	 	 	}, 2000);
    	 	 	loadFenceOK(data);
    	 	},
    	 	error: function(a, b) {
    	 	 	thiz.error("Cannot load fence data, reason given: '"+a+"':'"+b+"'");
    	 	}
    	});
    };
    var loadFenceOK=function(data) {
        var ll=[];
        var i;
        fencers=data;
        if (data.fence) {
            ll=JSON.parse(data.fence);
    	    for (i=0; i<ll.length; i++) {
    	 	L.marker([ll[i].lat, ll[i].lng], {icon: reddot}).addTo(map).on('click', removeDot);
    	    }
    	}
    	fence=L.polygon(ll, {color: 'red'}).addTo(map);
    	//
    	// position map to fit car & fence in browser window
    	//
    	ll=fence.getLatLngs();
    	var b=L.latLngBounds(ll);
    	b.extend(car.getLatLng());
    	map.fitBounds(b, {animate: true, duration: 2.0});
    	$('#save').prop( "disabled", ll.length <= 2 );
    	$('#load').prop( "disabled", false);
    };
  8. ダッシュボードには、ジオフェンス・エディターもあります。地図上のある地点をクリックすると、その位置がポリゴンに追加されて、ジオフェンスのエリアを定義します。赤いドットのいずれかをクリックすると、その地点がジオフェンスのポリゴンから削除されます。
    1. その特定の地点をポリゴンから削除するために、ループ処理を利用して、ポリゴン内に含まれる座標を、Leaflet 内で作成されたアイコンの座標と比較します。座標が一致すると、その地点がポリゴンから削除されるという仕組みです。
          //
            // fence editor (very basic)
          //
          var removeDot=function(me) {
      	 	var ll=fence.getLatLngs();
      	 	var i, l=ll.length;
      	 	for (i=0; i<l; i++) {
      	 	 	var p=ll[i];
      	 	 	var dx=p.lat-me.latlng.lat; // distance of a dot in fence to position clicked on map
      	 	 	var dy=p.lng-me.latlng.lng;
      	 	 	if (dy === 0 || dx === 0) {
      	    		fence.spliceLatLngs(i, 1);
      	    		l--;
      	    		break;
      	 	 	}
      	 	}
      	 	 
      	 	map.removeLayer(me.target);	// delete dot clicked on;
      	 	$('#save').prop( "disabled", l <= 2 );
      
          };
    2. ポリゴンに地点を追加するには、必要な作業が多少増えます。そのためのコードでは、中間に新しい地点を追加するのに最適な 2 つの地点をポリゴン内で見つけなければならないためです。その際にダッシュボード・アプリが実行するステップは以下のとおりです。
      • 地図上でクリックされた地点の座標に最も近い地点を見つけます。
      • その地点の隣にある 2 つの地点から、地図上でクリックされた地点に近い側の地点を判別します。
      • この 2 つの地点の間に、新しい地点を挿入します。

      (ほぼ) 空のポリゴンと「Save (保存)」ボタンを処理する JavaScript コードは、以下に示すような内容になります。

      var addDot=function(me) {
          	// see which existing dot is close to the mouse event me as p1
          	// find the adjacent nodes of p1 closest to me
          	// insert me between them
          	var ll=fence.getLatLngs();
          	var i, l=ll.length;
          	var p0=me.latlng, p1=null, p2=null;
          	if (l < 2) {
          	 	// there is no or only one dot in the fence - just add anew one
          	 	fence.addLatLng([ok, good, me.latlng.lng]);
          	} else {
          	 	var dist=0x07ffffff;	// max 32bit signed int
      	    	var p, dlat, dlng;
      	    	var d=Math.sqrt(dlat*dlat+dlng*dlng);
      	    	for (i=0; i<l; i++) {
      	    		p=ll[i];
      	    		dlat=p0.lat-p.lat;
      	    		dlng=p0.lng-p.lng;
      	    		d=Math.sqrt(dlat*dlat+dlng*dlng);
      	    		if (d < dist) {
      	    			p1=i;
      	    			dist=d;
      	    		}
      	    	}
      	    	// find closest adjacent
          	 	p2=(p1+l-1)%l;
          	 	p=ll[p2];
          	 	dlat=p0.lat-p.lat;
          	 	dlng=p0.lng-p.lng;
      	    	dist=Math.sqrt(dlat*dlat+dlng*dlng);
      	    	
          	 	p=ll[(p1+l+1)%l];
          	 	dlat=p0.lat-p.lat;
           	 	dlng=p0.lng-p.lng;
      	    	d=Math.sqrt(dlat*dlat+dlng*dlng);
      	    	if (d < dist) p2=(p1+l+1)%l;
      	    	console.log("add dot @"+p1+"/"+p2);
      	    	if (p1 > p2) { var t=p1; p1=p2; p2=t;}
      	    	// special case: p1 and p2 are beginning and end of array
        	    	if (p1 === 0 && p2 === l-1) {
      	    		fence.addLatLng(p0);
      	    	} else {
      	    		fence.spliceLatLngs(p2, 0, p0);
      	    	}
          	}
      	L.marker(me.latlng, {icon: reddot}).addTo(map).on('click', removeDot);
      	$('#save').prop( "disabled", l+1 <= 2 );
          };

      ポリゴン内の地点は Leaflet アイコンとして実装されていて、このアイコンをユーザーがクリックした時点でトリガーするコールバックが指定されています。したがって、ある地点がポリゴンから削除されると、その地点に関連付けられているアイコンが地図から削除されることになります。このコードにより、ユーザーがクリックした目的が、ある地点をジオフェンスのポリゴンに追加するためなのか、ポリゴンから削除するためなのかを簡単に判別できます。

http://car-meets-home.mybluemix.net/ にアクセスすると、Bluemix 上でデモ・ダッシュボードの動作を確認できます。

まとめ

このチュートリアルでは、Bluemix アプリを作成するにはどのようにするのか、Raspberry Pi を Watson IoT Platform に登録するにはどのようにするのか、デバイス・データにアクセスできるようにするにはどのようにするのか、そして送信されてくるデータを処理する Node-RED アプリを、MQTT プロトコルを使用して作成するにはどのようにするのかを説明しました。

さらに、Raspberry Pi 上に、Bluetooth 信号の強度を報告し、Bluemix アプリケーションから送信されるコマンドを受信する MQTT クライアントを作成しました。

この基本的なアプリケーションは、外部デバイスから GPS 座標を受信するための関数、Bluetooth 信号の強度、そしてジオロケーションが定義済みジオフェンスの内側または外側にあるかに応じて電化製品の電源をオンにするタイミングを決定するための関数などを新しく追加することによって迅速、簡単に拡張できます。チュートリアルでは最後に、GPS 制御機能に対してジオフェンスを定義する際、および Bluetooth 近接センサーの感度を設定する際に使用するダッシュボードも作成しました。Node-RED アプリにほんのわずかな数のノードを追加するだけで、必要な関数を API として追加することができました。

ここで学んだ知識を披露するために、皆さんの自動車を自宅につなげてください。


ダウンロード可能なリソース


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing
ArticleID=1039733
ArticleTitle=IoT を自宅に導入する: 自動車と自宅をつなげる
publish-date=11242016