IoTデータの管理

Tour Guide Applicationを使用すると、IoTデバイスからのデータを生成、シミュレートし、永続化することができます。 そのために、レストランのキッチンやダイニングルーム用の温度と湿度(架空の)センサーを生成します。 センサーによって提供されるすべてのデータは、デフォルトでMySQLデータベースを使用して、Cygnusに渡されます。

必要なサービス(tourguide, orion, idas, cygnusのコンテナ)が稼働していることを確認します。 以下を実行することによって:

./tour-guide start tourguide

まだ実行されていないすべてのサービスが開始されます。

起動が完了したら、センサーで作業を開始できます。

センサーの操作

Tour Guide Applicationでは、センサーを操作するさまざまな方法を提供しています:

$ ./tour-guide sensors
Usage: tour-guide sensors [-h | --help] <command> <options>

Run sensors related commands:

  create                    Create sensors for the restaurants available in the application.
  update                    Update all restaurant sensors measurements.
  send-data                 Send a single measurement for a specific sensor.
  simulate-data             Simulate a sensor sending data over a period of time.

Command options:

  -h  --help                Show this help.

Use 'tour-guide sensors <command> --help' to get help about a specific <command>.

センサーの作成

センサーの作成は実行するだけで簡単です:

./tour-guide sensors create

これにより、アプリケーションで、利用可能なレストランごとに4つのセンサーが作成され、初期化されます。レストランのキッチンとダイニングルームの両方に温度センサーと相対湿度センサーがあります。 このコマンドは、IoT Agent APIを使用してセンサーを作成し、デフォルト測定値でセンサーを初期化するスクリプト (sensorsgenerator.js) を実行します。

同様に、センサーを自分で作成する場合は、次の手順を実行します:

IoT Agentに新しいサービスを登録する

最初のステップは、新しいサービス構成をIoT Agentに登録することです(存在しない場合)。 これを行うには、次のJSONペイロードでhttp://localhost:4041/iot/servicesにPOSTリクエストを送信する必要があります:

{
    "services": [
        {
            "apikey": "tourguide-devices",
            "cbroker": "http://orion:1026",
            "resource": "/iot/d",
            "entity_type": "Restaurant"
        }
    ]
}
リクエストを送信する際には、次のHTTPヘッダーを含める必要があります:

  • Fiware-Service, Tour Guide Applicationでは、tourguideの値を指定します
  • Fiware-ServicePath, センサーを登録したいレストランの組織, 例えば、/Franchise1, これにより、その組織に属しているレストランのセンサーを登録することができます
  • Content-type of the data we are POSTing, これはapplication/jsonになります

これでリクエストを行うことができます:

$ (curl -H 'content-type: application/json' -H 'fiware-service: tourguide' -H 'fiware-servicepath: /Franchise1' -X POST 'http://localhost:4041/iot/services' -d @- ) << EOF
{
    "services": [
        {
            "apikey": "tourguide-devices",
            "cbroker": "http://orion:1026",
            "resource": "/iot/d",
            "entity_type": "Restaurant"
        }
    ]
}
EOF

エラーがなく、IoTエージェントのログに次のようなエントリがある場合、レスポンスは{}になります:

time=2016-09-29T11:12:35.920Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Request for path [/iot/services] from [localhost:4041] | comp=IoTAgent
time=2016-09-29T11:12:35.920Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Body:

{
    "services": [
        {
            "apikey": "tourguide-devices",
            "cbroker": "http://orion:1026",
            "resource": "/iot/d",
            "entity_type": "Restaurant"
        }
    ]
}

 | comp=IoTAgent
time=2016-09-29T11:12:35.923Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Creating new set of 1 services | comp=IoTAgent
time=2016-09-29T11:12:35.923Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Looking for entity params ["resource","apikey"] | comp=IoTAgent
time=2016-09-29T11:12:35.930Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Device group for fields [["resource","apikey"]] not found: [{"resource":"/iot/d","apikey":"tourguide-devices"}] | comp=IoTAgent
time=2016-09-29T11:12:35.935Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Storing device group with id [57ecf7235755b6010061870a], type [Restaurant], apikey [tourguide-devices] and resource [/iot/d] | comp=IoTAgent
この情報はMongoDBのデータベースに保存されます。 これを次のようにチェックすることができます:
$ docker exec -i -t mongodb mongo
MongoDB shell version: 2.6.11
connecting to: test
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
    http://docs.mongodb.org/
Questions? Try the support group
    http://groups.google.com/group/mongodb-user

使用可能なデータベースをリストし、IoTエージェントiotagentulが使用するデータベースを選択することができます。

> show dbs;
admin       (empty)
iotagentul  0.031GB
local       0.031GB
orion       0.031GB
> use iotagentul;
switched to db iotagentul
このデータベースには、2つのコレクション、devicesおよびgroupsがあります。 登録したばかりのサービスは、groupsコレクション内にあるはずです。
> show collections;
devices
groups
system.indexes
> db.groups.find();
{ "_id" : ObjectId("57ecf7235755b6010061870a"), "subservice" : "/Franchise1", "service" : "tourguide", "type" : "Restaurant", "apikey" : "tourguide-devices", "resource" : "/iot/d", "staticAttributes" : [ ], "__v" : 0 }
このように、サービスは保存されています。 次にセンサーを登録します。

新しいセンサーをIoTエージェントに登録する

新しい温度センサーを登録するには、次のJSONペイロードでhttp://localhost:4041/iot/devicesにPOSTリクエストを送信する必要があります:

{
    "devices": [
        {
            "device_id": "0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature",
            "entity_name": "0115206c51f60b48b77e4c937835795c33bb953f",
            "protocol": "UL20",
            "entity_type": "Restaurant",
            "timezone": "Europe/Madrid",
            "attributes": [
                {
                    "object_id": "t",
                    "name": "temperature:kitchen",
                    "type": "Number"
                }
            ]
        }
    ]
}
entity_name will be the Id of the restaurant to which we want to add the sensor, and device_id will be the Id of the sensor. In this example, we'll use the restaurant with Id 0115206c51f60b48b77e4c937835795c33bb953f. The Id of the sensor will be a compound of the restaurant Id, the room and the type of the sensor, like 0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature. entity_nameはセンサーを追加するレストランのIDになり、device_idはセンサーのIDになります。 この例では、IDが0115206c51f60b48b77e4c937835795c33bb953fのレストランを使用します。 センサーのIDは、レストランID, 部屋, センサーのタイプを組み合わせた合わせもの0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperatureになります。

サービスと同様に、リクエストに次のHTTPヘッダーを追加する必要があります:

  • Fiware-Service, Tour Guide Applicationでは、tourguide の値を指定します
  • Fiware-ServicePath, それはレストランの組織を指定します。例では/Franchise1です
  • Content-type of the data we are POSTing, これはapplication/jsonになります

リクエストを実行:

$ (curl -v -H 'content-type: application/json' -H 'fiware-service: tourguide' -H 'fiware-servicepath: /Franchise1' -X POST 'http://localhost:4041/iot/devices' -d @- ) << EOF
{
    "devices": [
        {
            "device_id": "0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature",
            "entity_name": "0115206c51f60b48b77e4c937835795c33bb953f",
            "protocol": "UL20",
            "entity_type": "Restaurant",
            "timezone": "Europe/Madrid",
            "attributes": [
                {
                    "object_id": "t",
                    "name": "temperature:kitchen",
                    "type": "Number"
                }
            ]
        }
    ]
}
EOF
そして、エラーがなければ応答は{}になります。 IoT Agentのログには、次のようなエントリが必要です:
time=2016-09-29T12:55:54.992Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Request for path [/iot/devices] from [localhost:4041] | comp=IoTAgent
time=2016-09-29T12:55:54.992Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Body:

{
    "devices": [
        {
            "device_id": "0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature",
            "entity_name": "0115206c51f60b48b77e4c937835795c33bb953f",
            "protocol": "UL20",
            "entity_type": "Restaurant",
            "timezone": "Europe/Madrid",
            "attributes": [
                {
                    "object_id": "t",
                    "name": "temperature:kitchen",
                    "type": "Number"
                }
            ]
        }
    ]
}

 | comp=IoTAgent
time=2016-09-29T12:55:54.993Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Handling device provisioning request. | comp=IoTAgent
time=2016-09-29T12:55:54.995Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Looking for entity with id [0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature]. | comp=IoTAgent
time=2016-09-29T12:55:54.997Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Entity [0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature] not found. | comp=IoTAgent
time=2016-09-29T12:55:54.997Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Looking for entity params ["service","subservice","type"] | comp=IoTAgent
time=2016-09-29T12:55:54.999Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Registering device into NGSI Service:
{
    "id": "0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature",
    "type": "Restaurant",
    "name": "0115206c51f60b48b77e4c937835795c33bb953f",
    "service": "tourguide",
    "subservice": "/Franchise1",
    "active": [
        {
            "object_id": "t",
            "name": "temperature:kitchen",
            "type": "Number"
        }
    ],
    "staticAttributes": [],
    "lazy": [],
    "commands": [],
    "timezone": "Europe/Madrid",
    "protocol": "UL20",
    "internalId": null,
    "subscriptions": []
} | comp=IoTAgent
time=2016-09-29T12:55:55.000Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=No Context Provider registrations found for unregister | comp=IoTAgent
time=2016-09-29T12:55:55.109Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Initial entity created successfully. | comp=IoTAgent
time=2016-09-29T12:55:55.110Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Storing device with id [0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature] and type [Restaurant] | comp=IoTAgent
time=2016-09-29T12:55:55.120Z | ... | srv=tourguide | subsrv=/Franchise1 | msg=Device provisioning request succeeded | comp=IoTAgent

今回は、devicesコレクションを使用して、Mongoデータベースを確認できます:

$ docker exec -i -t mongodb mongo
MongoDB shell version: 2.6.11
connecting to: test
> use iotagentul;
switched to db iotagentul
> db.devices.find();
{ "_id" : ObjectId("57ed0f5b5755b6010061870b"), "protocol" : "UL20", "internalId" : null, "subservice" : "/Franchise1", "service" : "tourguide", "name" : "0115206c51f60b48b77e4c937835795c33bb953f", "type" : "Restaurant", "id" : "0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature", "creationDate" : ISODate("2016-09-29T12:55:55.109Z"), "subscriptions" : [ ], "active" : [ { "type" : "Number", "name" : "temperature:kitchen", "object_id" : "t" } ], "__v" : 0 }

ご覧のように、デバイスはIoT Agentに登録されています。 Orionの既存エンティティにセンサーを追加するので、もう一度チェックしてください。 レストランのorionにリクエストして、新しい属性が追加されているかどうかを確認できます:

$ curl -s -H 'Fiware-Service: tourguide' http://localhost:1026/v2/entities/0115206c51f60b48b77e4c937835795c33bb953f | json_reformat
{
    "id": "0115206c51f60b48b77e4c937835795c33bb953f",
    "type": "Restaurant",
    "address": {
        "type": "PostalAddress",
        "value": {
            "streetAddress": "Cuesta de las Cabras Aldapa 2",
            "addressRegion": "Araba",
            "addressLocality": "Alegr鱈a-Dulantzi",
            "postalCode": "01240"
        },
        "metadata": {}
    },

    ...

    "temperature:kitchen": {
        "type": "Number",
        "value": " ",
        "metadata": {}
    }
}

ご覧のように、新しい属性temperature:kitchenがレストランのエンティティに追加されました。 まだ値を送信していないので、値は空であることに注意してください。

センサーの更新

センサーを登録したら、測定値を送信することができます。tourguide CLIを使用して実行します:

./tour-guide sensors update
これは、センサーの現在の値が取得し、小さな変化が得られ、使用可能なセンサーごとに新しい測定値を送信します。 これを自分自身で実行したい場合は、HTTP Ultralight 2.0 protocolを使用して新しい測定値を送信できます。 これを行う方法の詳細については、以下のSend dataを参照してください。

データを送信する

1つのセンサーを更新したい場合は、 tourguide CLIのsend-dataコマンドを使用してください:

$ ./tour-guide sensors send-data --help
Usage: tour-guide sensors send-data [-h | --help] [-i <sensorId> | --sensor-id <sensorId>]
                                    [ -d <ul20-string> | --data <ul20-string> ]

Ultralight 2.0文字列を使用して、特定のセンサーの単一の測定値を送信します。

Command options:

  -h  --help                Show this help.

Required parameters:

  -i  --sensor-id  <sensorId>   The sensor Id to modify.  The Id format is '<restaurantId>-<room>-<type>', with
                                <restaurantId> being the Id of the restaurant where the sensor is located,
                                <room> the room of the restaurant: kitchen, diner,
                                <type> the type of the sensor: temperature, relativeHumidity.
  -d  --data <ul20-string>      The string to send with the new measurement.  Examples of this are:
                                't|20' for temperature (20 C),
                                'h|0.4' for relativeHumidity (40%).

ここでは、Ultralight 2.0文字列を使用してセンサーIDと新しい測定値を指定する必要があります。 この例の続きで、前に作成したセンサーの温度を25度にしたいと考えています。 センサーIDは0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperatureであり、送信するデータ列はt|25です:

./tour-guide sensors send-data -i 0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature -d 't|25'
リクエストが成功した場合、出力はありません。 tourguide CLIを使用する代わりに、自分自身で測定値を送信したい場合は、http://localhost:7896/iot/d にPOSTリクエストを送信して、次のパラメータを追加することができます:

  • k=${api_key}
  • i=${sensor_id}

Here, the ${api_key} value is the one we defined when registering the service. In our example it is tourguide-devices. The ${sensor_id} is the Id of the sensor we want to update. In our example it is 0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature. ここで、${api_key}値は、サービス登録時に定義した値です。 この例では、tourguide-devicesです。 ${sensor_id}は、更新したいセンサーのIDです。 この例では、0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperatureです。

リクエストにContent-Type: text/plainのHTTPヘッダーを追加し、Ultralight 2.0データ文字列をペイロードとして送信する必要があります:

curl -v -X POST -H 'content-type: text/plain' 'http://localhost:7896/iot/d?k=tourguide-devices&i=0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature' -d 't|25'

リクエストが成功した場合、出力はありません。 次に、値が更新されたかどうかを確認するためにアトリビュートをチェックできます:

$ curl -s -H 'Fiware-Service: tourguide' http://localhost:1026/v2/entities/0115206c51f60b48b77e4c937835795c33bb953f/attrs/temperature:kitchen  | json_reformat
{
    "type": "Number",
    "value": "25",
    "metadata": {}
}
ご覧のように、temperature:kitchenアトリビュート値は25に更新されています。

データをシミュレートする

最後に、tourguide CLIのsimulate-dataコマンドを使用して、センサの測定値を定期的に送信することで、センサの動作をシミュレートできます:

$ ./tour-guide sensors simulate-data --help
Usage: tour-guide sensors simulate-data [-h | --help] [-i <sensorId> | --sensor-id <sensorId>]
                                        [ -t <type> | --type <type> ] [ -d <n> | --delay <n> ]

Simulate a sensor periodically sending data.

Command options:

  -h  --help                Show this help.

Required parameters:

  -i  --sensor-id  <sensorId>   The sensor Id to modify.  The Id format is '<restaurantId>-<room>-<type>', with
                                <restaurantId> being the Id of the restaurant where the sensor is located,
                                <room> the room of the restaurant: kitchen, diner,
                                <type> the type of the sensor: temperature, relativeHumidity.
  -t  --type <type>             Type of the sensor.  This must be the same type specified in the sensor Id.
                                Valid values: temperature, relativeHumidity.
  -d  --delay <n>               Delay in seconds between sensor readings.

このコマンドは、指定したセンサーの現在の値を取得し、小さい値(0と5の間)を加算または減算してセンサーを更新し、指定した間隔でプロセスを繰り返します。例に従えば、以下を行うことができます:

$ ./tour-guide sensors simulate-data -i 0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperature -t 'temperature' -d 30
これにより、0115206c51f60b48b77e4c937835795c33bb953f-kitchen-temperatureセンサーの新しい温度測定値 temperature30秒ごとに送信されます。 測定の送信を停止するには、Control + Cを使用してコマンドを中断します。このコマンドは、前のセクションで説明した新しい測定値の送信と同じ方法を使用します。 前と同じように、レストランのエンティティに保存されている現在の値をチェックするか、次のリクエストを使用して属性の値を取得することができます。
curl -s -H 'Fiware-Service: tourguide' http://localhost:1026/v2/entities/0115206c51f60b48b77e4c937835795c33bb953f/attrs/temperature:kitchen | json_reformat
{
    "type": "Number",
    "value": "25",
    "metadata": {}
}