FIWARE Orion で Lチカする
Lチカ (エルチカ) とは、プログラムから LED を制御してチカチカと点滅させる操作のことで、マイコン工作の “Hello World!” です。本記事では、FIWARE を使った、Lチカを紹介します。
FIWARE は、センサからコンテキスト情報を収集するだけでなく、デバイスを制御することもできます。Orion のコンテキスト情報の属性値を変更することで、デバイスの状態を変更できます。本記事では、LED が接続された、Ultralight 2.0 対応デバイス を作成して、これを Orion から制御して、Lチカを実現します。
サーバ側には、Orion と IoT Agent for Ultralight 2.0 をデプロイします。デバイスには、IoT マイコンの ESP32 を使用し、Ultralight 2.0 に対応したデバイスを作成します。
サーバ環境の作成
Orion と IoT Agent for Ultralight 2.0 は、Docker コンテナを利用して、サーバ上にデプロイします。docker-compose ファイルは次のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
version: "3" services: mongo: container_name: mongo restart: always image: mongo:3.4 command: --nojournal ports: - 127.0.0.1:27017:27017 orion: container_name: orion restart: always image: fiware/orion:2.0.0 depends_on: - mongo links: - mongo ports: - "1026:1026" command: -dbhost mongo iot-agent: container_name: fiware-iot-agent restart: always image: fiware/iotagent-ul:1.7.0 hostname: iot-agent depends_on: - mongo expose: - "4041" - "7896" ports: - "4041:4041" - "7896:7896" environment: - "IOTA_CB_HOST=orion" - "IOTA_CB_PORT=1026" - "IOTA_NORTH_PORT=4041" - "IOTA_REGISTRY_TYPE=mongodb" - "IOTA_LOG_LEVEL=DEBUG" - "IOTA_TIMESTAMP=true" - "IOTA_MONGO_HOST=mongo" - "IOTA_MONGO_PORT=27017" - "IOTA_MONGO_DB=iotagentul" - "IOTA_HTTP_PORT=7896" - "IOTA_PROVIDER_URL=http://iot-agent:4041" |
正常性の確認
Orion のバージョン取得や、IoT Agent に次のクエリを実行して、正しくデプロイされたことを確認してください。(サーバの IP アドレスを 192.168.1.1 として説明しています)
次のようなレスポンスが返ってくることを確認してください。
1 2 3 4 5 6 |
{ "libVersion": "2.7.0", "port": "4041", "baseRoot": "/", "version": "1.7.0" } |
Ultralight 2.0 対応デバイスの作成
ESP32 を利用して、Ultralight 2.0 対応デバイスの作成します。ESP32 に LED をひとつ接続しておきます。プログラムは次のとおりです。このプログラムのポイントは、execCmd() 関数です。IoT Agent からのリクエストをポート 80 で待ち受ける Web サーバで、IoT Agent から /iot/led001 へ POST リクエストを受け付けます。POST の Payload は、Ultralight 2.0 形式で、LED の ON/OFF の状態を表すパラメータが含まれてます。これにしたがって、LED の状態を変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
/** * iot-device-actuator.ino * * Iot Device Actuator * * Copyright 2018 Kazuhito Suda * * Created on: December 8, 2018 * */ #include <WiFi.h> #include <WiFiClient.h> #include <WebServer.h> char essid[] = "your essid"; char passphrase[] = "your passphrase"; const char url[] = "/iot/led001"; const char device[] = "led001"; const int led = 19; WebServer server(80); void setup() { pinMode(led, OUTPUT); digitalWrite(led, 0); Serial.begin(115200); Serial.println("Start"); connectWifi(); server.on(url, execCmd); server.onNotFound(handleNotFound); server.begin(); } void loop() { server.handleClient(); } void execCmd() { if (server.method() == HTTP_POST && server.args() == 1) { int status = 200; int atmark; int pipe; String postData = server.arg(0); Serial.println(postData); if (postData.startsWith(device) && (atmark = postData.indexOf('@')) != -1 && (pipe = postData.indexOf('|', atmark+1)) != -1) { String cmd = postData.substring(atmark+1, pipe); if (!cmd.compareTo("on")) { digitalWrite(led, 1); postData += cmd + " OK"; } else if (!cmd.compareTo("off")) { digitalWrite(led, 0); postData += cmd + " OK"; } else { postData += cmd + " ERROR"; status = 400; } } else { postData += "ERROR"; status = 400; } Serial.println(postData); server.send(status, "text/html", postData); } else { sendErrorMessage(400, "BadRequest", "service not found"); } } void handleNotFound() { sendErrorMessage(400, "BadRequest", "service not found"); } void sendErrorMessage(int status, String err, String description) { digitalWrite(led, 1); String message = "{\"error\":\"" + err + "\",\"description\":\"" + description + "\"}"; server.send(status, "application/json", message); digitalWrite(led, 0); } void connectWifi() { WiFi.mode(WIFI_STA); WiFi.begin(essid, passphrase); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(100); } Serial.println(""); Serial.println("Connected"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } |
IoT デバイスの接続
IoT デバイスにプロビジョニングします。最初にサービス・グループをプロビジョニングし、次にデバイスをプロビジョニングします。
サービス・グループのプロビジョニング
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/bin/sh curl -iX POST \ 'http://192.168.1.1:4041/iot/services' \ -H 'Content-Type: application/json' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' \ -d '{ "services": [ { "apikey": "x3knfo18xf28ekqbs93zmroz9f", "cbroker": "http://192.168.1.1:1026", "entity_type": "Thing", "resource": "/iot/d" } ] }' |
デバイスのプロビジョニング
“on”, “off” のコマンドを持つデバイスを、DeviceID : “led001”, Entity 名 : “urn:ngsi-ld:Led:001” としてプロビジョニングします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#!/bin/sh curl -iX POST \ 'http://192.168.1.1:4041/iot/devices' \ -H 'Content-Type: application/json' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' \ -d '{ "devices": [ { "device_id": "led001", "entity_name": "urn:ngsi-ld:Led:001", "entity_type": "Led", "protocol": "PDI-IoTA-UltraLight", "transport": "HTTP", "endpoint": "http://192.168.1.2/iot/led001", "commands": [ {"name": "on","type": "command"}, {"name": "off","type": "command"} ] } ] } ' |
デプロイしたデバイスの確認
デプロイしたデバイスのエンティティがあるか、Orion のクエリを実行して確認してみます。エンティティ名は、”urn:ngsi-ld:Led:001″ なので、次のクエリを実行します。
クエリ
1 2 3 4 |
#!/bin/sh curl -sS -X GET 'http://192.168.1.1:1026/v2/entities/urn:ngsi-ld:Led:001' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' |
実行結果
以下のようなレスポンスがあれば、エンティティが存在します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
{ "id": "urn:ngsi-ld:Led:001", "type": "Led", "TimeInstant": { "type": "ISO8601", "value": "2018-12-08T07:55:01.00Z", "metadata": {} }, "off_info": { "type": "commandResult", "value": "off OK", "metadata": { "TimeInstant": { "type": "ISO8601", "value": "2018-12-08T07:55:01.064Z" } } }, "off_status": { "type": "commandStatus", "value": "OK", "metadata": { "TimeInstant": { "type": "ISO8601", "value": "2018-12-08T07:55:01.064Z" } } }, "on_info": { "type": "commandResult", "value": "on OK", "metadata": { "TimeInstant": { "type": "ISO8601", "value": "2018-12-08T07:54:08.123Z" } } }, "on_status": { "type": "commandStatus", "value": "OK", "metadata": { "TimeInstant": { "type": "ISO8601", "value": "2018-12-08T07:54:08.123Z" } } }, "on": { "type": "command", "value": "", "metadata": {} }, "off": { "type": "command", "value": "", "metadata": {} } } |
L チカの実行
先ほど確認した、エンティティの属性情報を変更することで、LEDの点滅を制御できます。具体的な次のクエリを実行します。
LED を点灯するクエリ
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/bin/sh curl -iX PATCH \ 'http://192.168.1.1:1026/v2/entities/urn:ngsi-ld:Led:001/attrs' \ -H 'Content-Type: application/json' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' \ -d '{ "on": { "type" : "command", "value" : "" } }' |
LED を消灯するクエリ
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/bin/sh curl -iX PATCH \ 'http://192.168.1.1:1026/v2/entities/urn:ngsi-ld:Led:001/attrs' \ -H 'Content-Type: application/json' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' \ -d '{ "off": { "type" : "command", "value" : "" } }' |
シリアル・コンソールの出力
シリアル・コンソールには次のようなデータが出力されます。これには、IoT Agent から IoT デバイスへの Ultralight 2.0 形式のペイロードと、IoT デバイスから IoT Agent へのレスポンスが含まれています。
1 2 3 4 5 6 7 8 9 10 11 12 |
Start ....................................................... Connected IP address: 192.168.1.2 led001@on| led001@on|on OK led001@off| led001@off|off OK led001@on| led001@on|on OK led001@off| led001@off|off OK |