ThingsBoard / Data Pointsとその節減
ThingsBoard CloudのMessageとData Pointsの上限
ThingsBoard CloudにはDeviceからThingsBoardに送信できるTelemetry(センサーデータ)の数には時間あたりの上限が設けられています。
例えば Makerプランの All Transport messages (Tenant) の例です。
とあるテナント全体で200回/秒、6,000回/分、140,000回/時間を超えないように、とのことです。
以下のようなデータを1回送れば、messageも1加算されます。
{"temperature":25, "humidity":30}
上限を超えないようにデータの送信間隔を調整する必要があります。
時間あたりのMessage数の上限に加えて、ドキュメントにはData Pointsの上限というものがあります。
Data Pointsは1messageに含まれる最上位のkeyの数です。
公式のドキュメントの例を見てみます。公式ドキュメント
The following JSON contains 5 data points: temperature (double), humidity (integer), hvacEnabled (boolean), hvacState (string) and configuration (JSON):
{
"temperature": 42.2,
"humidity": 70,
"hvacEnabled": true,
"hvacState": "IDLE",
"configuration": {
"someNumber": 42,
"someArray": [1,2,3],
"someNestedObject": {"key": "value"}
}
}
引用文そのままですが、このmessageに含まれるData Pointsは5個となります。一定時間内のData Pointsの合計数にも上限が設けられているわけです。
Data Pointsの節減
課題
2025年2月現在、ThingsBoard Cloudの1Deviceに対するData Pointsの上限は、どのPlanであっても以下のように定められています。
Up to 200 per second, not exceeding 6,000 per minute, and capped at 14,000 per hour
1秒あたり200、1分あたり6,000、1時間あたり14,000です。1時間あたりの上限に注目して、1秒に1回データを送信するとなると、14,000 / 3,600 = 3.9 となります。つまり、1messageに4つのData Pointsが含まれるMessageを1秒間隔で送信すると上限に抵触してしまうことになります。
この上限は結構厳しいのでは、と個人的には思います。100msの粒度でデータ送信するのであれば1Data Pointずつの送信であっても1時間は継続できないことになりますし、あとでデータ分析するにもできる限り細かい粒度でデータを取得したいこともあるでしょう。
話が若干それますが、ThingsBoardの1Deviceに複数の実Deviceからデータを送信することでThingsBoardのDevice数を節約することができます。この場合、2つの実DeviceからThingsBoardの1Deviceに1秒間隔で1時間データを送り続けるとなると、1messageに含まれるData Pointsは2未満、つまり1に抑えなければなりません。
節減方法
ではData Pointsの節減方法です。その答えは上記しているに等しいのですが、送信したいデータの上位層にKeyを加えて、Data Points = 1に見せかければよいのです。
公式ドキュメントのJSONを使うとこのようになります。
{
"device": {
"temperature": 42.2,
"humidity": 70,
"hvacEnabled": true,
"hvacState": "IDLE",
"configuration": {
"someNumber": 42,
"someArray": [1,2,3],
"someNestedObject": {"key": "value"}
}
}
}
1 Data Pointに集約する前後で、ThingsBoard上のTelemetryがどのように変化したか確認してみます。
これで1messageあたりのData Pointsは5 -> 1に減らせました。
節減のDashboardへの影響と対応
上記のデータの作り方によってData Pointsを節減できますが、データのハンドリングに影響が出ます。特にDashboardの作り方にダイレクトに影響します。
集約前のデータで、temperatureの値をValue Card widgetで表示させるとすると、このような設定になるかと思います。
では、集約後のデータでtemperatureの値を取り出すにはどうすればよいでしょうか。Post-processing functionという機能を使います。
新しくValue Card widgetを追加し、データを集約したData Pointが入っているkeyを選択します。keyの横に編集ボタンがありますのでこれをクリックします。
すると以下のような設定画面に移ります。Use data post-processing functionにチェックを入れ、下のテキストボックスにtemperatureを取り出すためのJavascriptの処理を書きます。
var temperature = JSON.parse(value).temperature;
if (typeof temperature == 'number') {
return temperature;
} else {
return null;
}
保存してDashboardを確認すると、集約後のデータからtemperatureの値を取り出して反映できています。
Javascriptの処理について
Post-processing functionにはJavascriptの処理を書くのですが、「ちょっと何言ってるかわからない」エラーが多発します。
例えば、さきほどの処理をこのように書き換えて保存しようとすると、 Function must return value!
とエラーが出ます。
var temperature = JSON.parse(value).temperature
return temperature;
よくよく見てみると value
(元の値)が temperature
というkeyを持たない場合、 変数temperature
には undefined
が入ります。これがエラーの原因なので条件分岐して undefined
を返却しないように条件分岐など適切な処理を施さなければなりません。
、、、などなど詰まってしまうケースが多発します。デバッグできればいいのですが、そのような機能もありません。が、処理途中の変数の値を出力できる方法があります。
以下のスクリプトを入力して保存し、その後Develper ToolのConsoleを開きつつ、WidgetのPreviewを見てみます。
var temperature = JSON.parse(value).temperature;
console.log("temperature", temperature);
if (typeof temperature == 'number') {
return temperature;
} else {
return null;
}
するとDeveloper Toolに console.log
の出力内容が表示されます。この処理はブラウザ上で動作しているっていうことですね。これで多少なりとも開発しやすくなるはずです。
まとめ
Data Pointsの節減方法とDashboardへの影響・対応について記載しました。装置によっては必ずしも必要な対応というわけではありませんが、ご活用いただければと思います。
Discussion