センサーのログを取得・蓄積する仕組みの作り方(Node-RED + Supabase(スーパベース))
概要
この教材では、IoTでお馴染みのセンサーを取得するところではなく、取得したデータを整形し、NoSQL型のデータベースシステムに蓄積、可視化する仕組みについて、自分で構築して学びます。下図のMongoDBの部分が、Supabase になります。
センサーを使ってデータを獲得する部分は、ArduinoやRaspberry Pi などいろいろありますが、プログラミングが苦手、書く時間が面倒な場合は、obniz が手軽です。
センサー取得するデータベース(Supabase)の用意
Supabaseの利用登録
Supabaseには、セルフホスト版とSaaS版があります。ここでは、SaaS版を使います。SupabaseのWebサイトにアクセスします。画面内の「Start your project」をクリックし、Supabaseの利用登録作業を行います。
Supabaseを用いたテーブルの作成
登録したユーザー名 Org のように表示されます。Supabaseにおける「Project」は、データベースになります。Supabaseは、PostgreSQLを土台にしたFirebaseの代替ソリューションであり、オープンソースソフトウェアです。商用利用しやすいMITライセンスが適用されるため、企業や自治体の案件につかうことができます。
画面左側の「Table Editor」をクリックします。
「Name」の欄に、sensor-data と入力します。他の値でも構いません。「Colums」には、下図のように「device」と「temp」を追加します。追加後、「Save」をクリックします。
このようなテーブルになります。
「SUPABASE_CLIENT_ANON_KEY」の確認
Supabaseのテーブルに、外部から接続するための「SUPABASE_CLIENT_ANON_KEY」の値を確認します。
確認には、Supabaseの画面左下の「Project Settings」の「API Keys」をクリックします。
API Keysの画面が表示されます。「anon」「public」と表示されている文字列をコピーします。この文字列が、API Keyです。「SUPABASE_CLIENT_ANON_KEY」を指定された場合は、このAPI Keyの値になります。
テーブル用ポリシーの作成
外部の仕組みからSupabaseに接続する際に、下記のようなエラーがでることがあります。
new row violates row-level security policy for table
この場合は、ポリシーが作成されていないことによるものです。Suapbaseの画面左側で、「Authentication」>>「Policies」をクリックします。
先ほど作成したテーブルの「Create policy」をクリックします。
表示されたポリシーのテンプレートで、「Policy with security definer functions」を選びます。また、画面内で「Policy Command」で「ALL」を選び、「USE OPTIONS ABOVE TO EDIT」の画面内で、using の{ }内に、true を記述し、「Save policy」をクリックします。
作成したポリシーが登録され、下図のように表示されます。
テーブルに接続するためのAPI接続情報の確認
作成したテーブルにアクセスします。
表示されたテーブルの画面で、「API Docs」をクリックします。
「Language」を「Bash」に変えます。また「Insert rows」に切り替えます。表示されている、REST API のPOST に必要な情報が表示されているので、コピーしておきます。
Obniz Boardの用意
下記を参考に、Obniz Boardに温度センサーを接続し、インターネットに接続します。
センサー取得データを取得する仕組み(Node-RED)の用意
ここでは、Github Codespacesを使って、クラウド上でNode-REDを起動しますので、下記を参考にNode-RED環境を用意します。
Github Codespaces を用いた開発環境および検証環境構築(Node-REDを例に)
Node-REDにSupabaseを接続
サンプルフロー「POST Supabase with Obniz」をNode-RED環境にインポート
サンプルを実装しましょう。下図のようなフローを作成します。
実装するための下記のJSONをコピーし、Node-REDにインポートします。
[
{
"id": "663a9488b57835a6",
"type": "tab",
"label": "POST Supabase with Obniz",
"disabled": false,
"info": "",
"env": []
},
{
"id": "b5e693c810309349",
"type": "inject",
"z": "663a9488b57835a6",
"name": "switch",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 90,
"y": 80,
"wires": [
[
"435771cdd38e7bcf"
]
]
},
{
"id": "435771cdd38e7bcf",
"type": "obniz-function",
"z": "663a9488b57835a6",
"obniz": "f21974a02e413dba",
"name": "",
"code": "let tempsens = obniz.wired(\"Keyestudio_TemperatureSensor\", {signal:0, vcc:1, gnd:2});\nlet temp = await tempsens.getWait();\nlet name = \"obnizboard\";\nmsg.payload = {\n device : name,\n temp : temp\n}\nreturn msg;",
"x": 180,
"y": 160,
"wires": [
[
"38501d4d5f162a63"
]
]
},
{
"id": "ab11117c7a7c3837",
"type": "http request",
"z": "663a9488b57835a6",
"name": "",
"method": "POST",
"ret": "txt",
"paytoqs": "ignore",
"url": "https://blseddkrtammuvvbzhxp.supabase.co/rest/v1/sensor-data",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "bearer",
"senderr": false,
"headers": [
{
"keyType": "other",
"keyValue": "apikey",
"valueType": "other",
"valueValue": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"keyType": "Content-Type",
"keyValue": "",
"valueType": "other",
"valueValue": "application/json"
},
{
"keyType": "other",
"keyValue": "Prefer",
"valueType": "other",
"valueValue": "return=minimal"
}
],
"x": 430,
"y": 260,
"wires": [
[
"eab76c3882dba353"
]
]
},
{
"id": "38501d4d5f162a63",
"type": "function",
"z": "663a9488b57835a6",
"name": "CREATE DATA",
"func": "let device = msg.payload.device;\nlet temp = msg.payload.temp;\nmsg.payload = {\n \"device\": device,\n \"temp\": temp\n}\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 420,
"y": 160,
"wires": [
[
"ab11117c7a7c3837",
"3534aa8b51acc4e4"
]
]
},
{
"id": "3534aa8b51acc4e4",
"type": "debug",
"z": "663a9488b57835a6",
"name": "Debug DATA",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 650,
"y": 160,
"wires": []
},
{
"id": "eab76c3882dba353",
"type": "debug",
"z": "663a9488b57835a6",
"name": "Debug HTTP Request",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 680,
"y": 260,
"wires": []
},
{
"id": "f21974a02e413dba",
"type": "obniz",
"obnizId": "XXXX-XXXX",
"deviceType": "obnizboard",
"name": "myObniz",
"accessToken": "",
"code": ""
}
]
コピーしたJSONを、Node-REDの画面で貼り付け、Import処理を行います。
インポートが成功すると、下図のように表示されます。
「Obniz function」ノードの設定
「obniz function」ノードで、自分のObniz機器(Obniz Board等)につながるように「obniz ID」を入力します。方法はわからない場合は、obnizによる温度の取得 ( サンプルの確認とNode-RED ) をご確認ください。
「obniz ID」を入力後、「Edit obniz-function node」内の「Function」の記述が下図のようになっていることを確認します。「let name」に挿入する文字列は、そのままでも構いませんが、適当なものに変えてください。「Done」をクリックして保存します。
「function」ノードの設定
サンプルフローでは、CREATE DATA と表示されているノードになります。ダブルクリックして開きます。動かすだけであれば、このままで動きます。「obniz function」ノードで取得した情報を、この後の「http request」ノードに渡すための中継ぎになります。
「device」と「temp」の2つの変数は、Supabaseで作成したテーブルの列の「device」と「temp」に該当します。ここで、Supabaseのテーブルに挿入するためのJSONデータを作成することが、このノードの役割です。
「http request」ノードの設定
「http request」と表示されている部分をダブルクリックして開きます。「Edit http request node」画面が表示されます。ここでは、Supabaseに接続するための設定を行います。次の各項目を設定します。
Method : POST に変えます。POSTを選ぶことで、Supabaseに新しいデータの登録ができるようになります。
URL : Supabseの画面で確認した、テーブルに接続するためのAPI接続情報に書かれたURLを記述します。コピー&ペーストしましょう。
Use authentication : チェックを入れる
Type : barrer authentication を選択
Token : 「SUPABASE_CLIENT_ANON_KEY」の値を記述します。コピー&ペーストしましょう。
APIのHeadersを設定します。追加したいヘッダー情報がある場合は、画面下の「add」で追加できます。
apikeyの値 : 「SUPABASE_CLIENT_ANON_KEY」の値を記述します。コピー&ペーストしましょう。
これらを記述後、「Done」をクリックします。
動作確認
ここまでの設定により、サンプルのフローが動くようになります。画面右上の「Deploy」をクリックします。
Node-REDのフローで、「switch」ノードの左端のボタンをクリックします。これがトリガーとなって、フローの処理がはじまります。「switch」ノードをダブルクリックして編集画面を呼び出せば、決まった時間に定期的に実行する設定を行うことができます。
フローが実行されることで、Obniz Board に接続した温度センサーの計測値を、deviceの変数に挿入した値で、Supabaseのテーブル、sensor_data に記録できるようになります。
Supabseのテーブルを確認すると、Node-REDから、REST API で、POSTされたことで、温度センサーの計測値が記録されていることがわかります。
その他の資料
Supabase以外にMongoDB の場合は、こちらです。センサーのログを取得・蓄積する仕組みの作り方(Node-RED + MongoDB Atlas)