Help us understand the problem. What is going on with this article?

IoT Edge を触ってみた

More than 1 year has passed since last update.

Azure の IoT Edge を触ってみた。たまたま社内のハッカソンがあった。私は社内のハッカソンの時は普段触っていない技術を触るようにしている。

Screen Shot 2017-10-17 at 10.34.54 PM.png

本当は、ML をやりたかったが、他にやっている人がいたので、今回は、IoT Edge を担当することになった。IoT Edge は、下記のビデオがわかりやすいが、Intelligent edge と呼ばれるサービスで、サーバーで動いているAzure Functions や、Stream Analytics そしてマシンラーニングを、ローカル(Edge) で動かせるとのことだ。

//build で見た時は相当衝撃だったので、今のうちに IoT Edge に触れておきたい。(ちなみに、現状では残念ながら上記の機能を持った IoT Edge 2.0 はリリースされていない様子。無念)ま、ともかく、今日学んだことをメモしておく。

IoT Edge のアーキテクチャ

試しに、Ubuntu 14.04 のマシンを Edge と見立ててサンプルが動く環境を作って見た。とてもスムースだった。

image2.png

Edge 側のアーキテクチャはとてもシンプルだ。(ver1.x) ポイントは、各モジュールが、Broker を経由してデータをやりとりしていること。また、ブローカーを通じて、IoT Hub の方とも通信する。
 ちなみに、Azure Functions も現在のバージョンでも、IoT Hubをサポートしているので、Broker を経由して、メッセージを投げると、IoT Hub にメッセージが送られて、そこからさらに、Azure Functions をキックするということが可能だ。

Edge のインストール

こちらもほぼ苦労したところがない。手順のまま。尚環境は、手元に、マシンがないので、Ubuntu 14.04 LTE で代用した。

関連ライブラリのインストール

sudo apt-get update
sudo apt-get install curl build-essential libcurl4-openssl-dev git cmake pkg-config libssl-dev uuid-dev valgrind libglib2.0-dev libtool autoconf

iot-edge ファイルの取得とビルド

git clone https://github.com/Azure/iot-edge.git
cd iot-edge
tools/build.sh --disable-natibe-remote-modules

ちなみに、samples/hello_world/src/hello_world_lin.json は次のようになっている。このような設定ファイルを見ていると、ブローカーのイメージがうっさらわかるかもしれない。これは、logger hello_world の二つの構成になっていて、hello_worldの出力をlogger に書き込んでいる。

hello_worldlin.json_

{
    "modules" :
    [
        {
            "name" : "logger",
            "loader": {
            "name": "native",
            "entrypoint": {
                "module.path": "./modules/logger/liblogger.so"
            }
            },
            "args" : {"filename":"log.txt"}
        },
        {
            "name" : "hello_world",
            "loader": {
            "name": "native",
            "entrypoint": {
                "module.path": "./modules/hello_world/libhello_world.so"
            }
            },
            "args" : null
        }
    ],
    "links":
    [
        {
            "source": "hello_world",
            "sink": "logger"
        }
    ]
}

バイナリのhello_world_sample を実行する。

./samples/hello_world/hello_world_sample ../samples/hello_world/src/hello_world_lin.json

出力はそのまま。マニュアル通りだった。

[{
    "time": "Mon Apr 11 13:42:50 2016",
    "content": "Log started"
}, {
    "time": "Mon Apr 11 13:42:50 2016",
    "properties": {
        "helloWorld": "from Azure IoT Gateway SDK simple sample!"
    },
    "content": "aGVsbG8gd29ybGQ="
}, {
    "time": "Mon Apr 11 13:42:55 2016",
    "properties": {
        "helloWorld": "from Azure IoT Gateway SDK simple sample!"
    },
    "content": "aGVsbG8gd29ybGQ="
}, {
    "time": "Mon Apr 11 13:43:00 2016",
    "properties": {
        "helloWorld": "from Azure IoT Gateway SDK simple sample!"
    },
    "content": "aGVsbG8gd29ybGQ="
}, {
    "time": "Mon Apr 11 13:45:00 2016",
    "content": "Log stopped"
}]

IoT Hub と接続する。

次はこちらのチュートリアル。こちらもほぼそのまんま。

samples/simulated_device_cloud_upload_sample/src/simulated_device_cloud_upload_lin.json を埋める。自分の

{
    "modules": [
        {
            "name": "IotHub",
          "loader": {
            "name": "native",
            "entrypoint": {
              "module.path": "./modules/iothub/libiothub.so"
            }
            },
            "args": {
              "IoTHubName": "removeiot",
              "IoTHubSuffix": "azure-devices.net",
              "Transport": "HTTP"
            }
          },
        {
            "name": "mapping",
          "loader": {
            "name": "native",
            "entrypoint": {
              "module.path": "./modules/identitymap/libidentity_map.so"
            }
            },
            "args": [
              {
                "macAddress": "01:01:01:01:01:01",
                "deviceId": "<<insert here deviceId>>",
                "deviceKey": "<<insert here deviceKey>>"
              }
            ]
          },
        {
            "name": "BLE1",
          "loader": {
            "name": "native",
            "entrypoint": {
              "module.path": "./modules/simulated_device/libsimulated_device.so"
            }
            },
            "args": {
              "macAddress": "01:01:01:01:01:01"
            }
          },
        {
            "name": "Logger",
          "loader": {
            "name": "native",
            "entrypoint": {
              "module.path": "./modules/logger/liblogger.so"
            }
            },
            "args": {
              "filename": "deviceCloudUploadGatewaylog.log"
            }
          }
    ],
    "links": [
        {
            "source": "*",
            "sink": "Logger"
        },
        {
            "source": "BLE1",
            "sink": "mapping"
        },

        {
            "source": "mapping",
            "sink": "IotHub"
        }
    ]
}

ちなみに、device id は、IoT Hub の方で、生成する。Device Explorer で作成できる。

Screen Shot 2017-10-17 at 11.30.02 PM.png

これで実行

./samples/simulated_device_cloud_upload/simulated_device_cloud_upload_sample ../samples/simulated_device_cloud_upload/src/simulated_device_cloud_upload_lin.json

ただ、これだと結果がわからないので、Azure Functions に繋いでみる

Azure Functions を生成してみる。

実は、現在の、Azure Functions では、IoT Hub に直接バインドすることができた。私の好きな、TypeScript + IoT Hub のバインディングスを使って繋いで見た。

特に解説はないが、最初message の持っているプロパティがわからなかったので、Object.getOwnPropertyNames で調べて見た。そして、ダンプして見た。

export function run(context: any, IoTHubMessages: any[]): void {
    context.log(`TypeScript eventhub trigger function called for message array ${IoTHubMessages}`);


    IoTHubMessages.forEach(message => {
        let names = Object.getOwnPropertyNames(message);
        context.log("properyName: " +names);
        context.log("temperature = " + message.temperature);

        context.log(`Processed message ${message}`);
    });

    context.done();
};

function.json

{
  "bindings": [
    {
      "type": "eventHubTrigger",
      "name": "IoTHubMessages",
      "direction": "in",
      "path": "samples-workitems",
      "connection": "removeiot_events_IOTHUB",
      "cardinality": "many",
      "consumerGroup": "$Default"
    }
  ],
  "disabled": false
}

IoT Edge からしっかりデータがきているのがわかる。

2017-10-17T14:35:08  Welcome, you are now connected to log-streaming service.
2017-10-17T14:36:05.464 Function started (Id=1dd2fa3e-83e0-456c-974c-6a2eec896dae)
2017-10-17T14:36:05.464 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:05.464 properyName: temperature
2017-10-17T14:36:05.464 temperature = 10
2017-10-17T14:36:05.464 Processed message [object Object]
2017-10-17T14:36:05.464 Function completed (Success, Id=1dd2fa3e-83e0-456c-974c-6a2eec896dae, Duration=7ms)
2017-10-17T14:36:07.051 Function started (Id=68e2efd1-54bb-4fe3-b275-15371b004a31)
2017-10-17T14:36:07.051 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:07.051 properyName: temperature
2017-10-17T14:36:07.051 temperature = 11
2017-10-17T14:36:07.051 Processed message [object Object]
2017-10-17T14:36:07.051 Function completed (Success, Id=68e2efd1-54bb-4fe3-b275-15371b004a31, Duration=1ms)
2017-10-17T14:36:09.050 Function started (Id=6da7743e-1070-4049-bc58-30c94901bdc4)
2017-10-17T14:36:09.050 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:09.050 properyName: temperature
2017-10-17T14:36:09.050 temperature = 12
2017-10-17T14:36:09.050 Processed message [object Object]
2017-10-17T14:36:09.050 Function completed (Success, Id=6da7743e-1070-4049-bc58-30c94901bdc4, Duration=1ms)
2017-10-17T14:36:11.048 Function started (Id=5dea256e-c500-4c4f-a404-17cdf3c76852)
2017-10-17T14:36:11.048 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:11.048 properyName: temperature
2017-10-17T14:36:11.048 temperature = 13
2017-10-17T14:36:11.048 Processed message [object Object]
2017-10-17T14:36:11.048 Function completed (Success, Id=5dea256e-c500-4c4f-a404-17cdf3c76852, Duration=0ms)
2017-10-17T14:36:13.057 Function started (Id=f82e8fc7-c171-4646-abbd-f1868bf64be5)
2017-10-17T14:36:13.057 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:13.057 properyName: temperature
2017-10-17T14:36:13.057 temperature = 14
2017-10-17T14:36:13.057 Processed message [object Object]
2017-10-17T14:36:13.057 Function completed (Success, Id=f82e8fc7-c171-4646-abbd-f1868bf64be5, Duration=0ms)
2017-10-17T14:36:15.101 Function started (Id=03da80a3-ebae-4019-96fd-d85c329553a3)
2017-10-17T14:36:15.101 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:15.101 properyName: temperature
2017-10-17T14:36:15.101 temperature = 15
2017-10-17T14:36:15.101 Processed message [object Object]
2017-10-17T14:36:15.101 Function completed (Success, Id=03da80a3-ebae-4019-96fd-d85c329553a3, Duration=1ms)
2017-10-17T14:36:17.064 Function started (Id=ed63f63b-9e58-4ed3-9fb2-a02cd59cdd4d)
2017-10-17T14:36:17.064 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:17.064 properyName: temperature
2017-10-17T14:36:17.064 temperature = 16
2017-10-17T14:36:17.064 Processed message [object Object]
2017-10-17T14:36:17.064 Function completed (Success, Id=ed63f63b-9e58-4ed3-9fb2-a02cd59cdd4d, Duration=1ms)
2017-10-17T14:36:19.064 Function started (Id=633e5861-d81d-4e1f-b3dd-9e50b135997e)
2017-10-17T14:36:19.064 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:19.064 properyName: temperature
2017-10-17T14:36:19.064 temperature = 17
2017-10-17T14:36:19.064 Processed message [object Object]
2017-10-17T14:36:19.064 Function completed (Success, Id=633e5861-d81d-4e1f-b3dd-9e50b135997e, Duration=0ms)
2017-10-17T14:36:21.062 Function started (Id=49cc53ae-7e9a-4344-a114-b9b6a380915f)
2017-10-17T14:36:21.062 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:21.062 properyName: temperature
2017-10-17T14:36:21.062 temperature = 18
2017-10-17T14:36:21.062 Processed message [object Object]
2017-10-17T14:36:21.062 Function completed (Success, Id=49cc53ae-7e9a-4344-a114-b9b6a380915f, Duration=1ms)
2017-10-17T14:36:23.048 Function started (Id=740a9a65-5554-4738-aaeb-670d49bff0d1)
2017-10-17T14:36:23.048 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:23.048 properyName: temperature
2017-10-17T14:36:23.048 temperature = 19
2017-10-17T14:36:23.048 Processed message [object Object]
2017-10-17T14:36:23.048 Function completed (Success, Id=740a9a65-5554-4738-aaeb-670d49bff0d1, Duration=1ms)
2017-10-17T14:36:25.057 Function started (Id=3bcd6cb6-7c29-4ca6-b0d8-f8271f24dda3)
2017-10-17T14:36:25.057 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:25.057 properyName: temperature
2017-10-17T14:36:25.057 temperature = 20
2017-10-17T14:36:25.057 Processed message [object Object]
2017-10-17T14:36:25.057 Function completed (Success, Id=3bcd6cb6-7c29-4ca6-b0d8-f8271f24dda3, Duration=1ms)
2017-10-17T14:36:27.060 Function started (Id=7240e6e5-f974-4490-9baf-f7550e09b6b1)
2017-10-17T14:36:27.060 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:27.060 properyName: temperature
2017-10-17T14:36:27.060 temperature = 21
2017-10-17T14:36:27.060 Processed message [object Object]
2017-10-17T14:36:27.060 Function completed (Success, Id=7240e6e5-f974-4490-9baf-f7550e09b6b1, Duration=1ms)
2017-10-17T14:36:29.069 Function started (Id=912b8bae-fc4c-47e2-bc73-0591316ef597)
2017-10-17T14:36:29.069 TypeScript eventhub trigger function called for message array [object Object]
2017-10-17T14:36:29.069 properyName: temperature
2017-10-17T14:36:29.069 temperature = 22
2017-10-17T14:36:29.069 Processed message [object Object]
2017-10-17T14:36:29.069 Function completed (Success, Id=912b8bae-fc4c-47e2-bc73-0591316ef597, 

ちなみに、Service Bus を経由して使う方法は昔はメジャーだったらしい。今は、Azure Functions 直接が主流ね。つまり下記のは古い。

終わりに

ちなみに、本当は、IoT Edge の Edge にコンテナダウンロードしたかったので、悔しいから、Functions をコンテナで動かせる Dockerfile 書いてみようかな。

あと、IoT Edge とくみあわせていい感じになりそうなサービスがあるので、次回試してみたい。ちなみにこのハックは日を空けて3日づつくので

Resource

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away