OpenHab2永続性のためのrrd4jの使用

OpenHabは「スマートホーム」(またはIoT、今では流行している)の人気のあるサーバーであり、Habréで既にレビューています。 ただし、サーバー構成の特定の側面に関するドキュメントは、必要なほど多くありません。 そして、ロシア語では、それを考慮しないでください。



OpenHabの重要な機能は、そのモジュール性です。 サーバー自体は基本的な機能を提供します(UIがなくても)。 他のすべての機能はプラグインによって提供されます。 プラグインのタイプの1つに永続性があります-アイテム(デバイスパラメーター)の値の履歴を保存する機能を提供します。 これは、履歴データ(グラフィック)を表示し、サーバーの再起動中にアイテムのステータスを復元するために必要です。



既存のプラグインを使用すると、一般的なすべてのデータベースをストレージに使用できます。 非常に興味深いバックエンド、rrd4jのセットアップについて説明します。 これは、データ用の高性能ストレージであり、期限付きの一連の値です。 著者はRRDToolsスイートに触発されましたが、その機能をJavaで書き直し(OpenHabもJavaで記述されています)、機能を最適化および拡張しました。 Rrd4jストレージファイルは、RRDToolsファイルと互換性がありません。



ここで、このリポジトリが何であるかを伝える必要があります。 これらは、時間参照とともにパラメーター値を保存する1つ以上の循環バッファーです。 同時に、複数の変更を1つのバッファ値に集約することができます(たとえば、1分ごとにデータを取得し、5分間の1つの平均値を保存します)。



したがって、永続性のないOpenHab2インストールがあります。 テストには、このボードを使用します。







2つのダラス18B20温度計とボード上のボタンがあります。







彼女はMySensorsを使用してサーバーと通信します。 ちなみに、MySensorsプロトコルのプラグインは何らかの理由でリポジトリにないため、手動で配置し、フォーラムトピックからダウンロードして、/ usr / share / openhab2 / addons /フォルダーに配置する必要があります。



同じ無線モジュールを備えた標準ゲートウェイは、USBを介してサーバーに接続されます。



ボードのファームウェア
// Enable debug prints to serial monitor #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 // Static node id #define MY_NODE_ID 1 #include <MySensors.h> #include <DallasTemperature.h> #define SKETCH_NAME "Test board" #define SKETCH_MAJOR_VER "1" #define SKETCH_MINOR_VER "0" // Item IDs #define CHILD_ID_BTN 3 #define CHILD_ID_TEMP 10 // Pin definitions #define PIN_BTN 2 #define PIN_BTN_LED 3 #define PIN_ONE_WIRE 7 // Messages MyMessage msgBtn(CHILD_ID_BTN, V_STATUS); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); //OneWire temperature OneWire oneWire(PIN_ONE_WIRE); DallasTemperature temp(&oneWire); #define MAX_TEMP_SENSORS 10 int cntSensors = 0; // Don't support hotplug float arrSensors[MAX_TEMP_SENSORS]; DeviceAddress arrAddress[MAX_TEMP_SENSORS]; void before() { temp.begin(); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER); // Present locally attached sensors present(CHILD_ID_BTN, S_BINARY); cntSensors = temp.getDeviceCount(); if (cntSensors > MAX_TEMP_SENSORS) cntSensors = MAX_TEMP_SENSORS; Serial.print("Temperature sensors found:"); Serial.print(cntSensors); Serial.println("."); for (int i = 0; i < cntSensors; i++) { present(CHILD_ID_TEMP + i, S_TEMP); arrSensors[i] = 0; temp.getAddress(arrAddress[i], i); } } void setup() { // Setup locally attached sensors pinMode(PIN_BTN, INPUT_PULLUP); pinMode(PIN_BTN_LED, OUTPUT); temp.setWaitForConversion(false); temp.setResolution(12); // 0,0625 grad celsius } void loop() { // Send locally attached sensor data here static unsigned long owNextConversTm = 0; if (0 == owNextConversTm) { temp.requestTemperatures(); int16_t owConversTm = temp.millisToWaitForConversion(temp.getResolution()); owNextConversTm = millis() + owConversTm + 50; // Wait a little more } else if (owNextConversTm < millis() && temp.isConversionComplete()) { for (int i = 0; i < cntSensors; i++) { if (temp.validFamily(arrAddress[i])) { int t1 = temp.getTempC(arrAddress[i]) * 10; float t = t1 / 10 + (t1 % 10) * 0.1; if (t != arrSensors[i]) { send(msgTemp.setSensor(CHILD_ID_TEMP + i).set(t, 1)); arrSensors[i] = t; Serial.print("Sensor #"); Serial.print(i); Serial.print(", temperature: "); Serial.print(t); Serial.println(" C."); } } } owNextConversTm = 0; } else if ((owNextConversTm + 30000) < millis()) { // It was couter reset owNextConversTm = 0; } static int currVal = HIGH; int val = digitalRead(PIN_BTN); if (val != currVal) { digitalWrite(PIN_BTN_LED, val == HIGH ? LOW : HIGH); send(msgBtn.set(val == LOW)); currVal = val; Serial.print("Btn state changed to "); Serial.println(val == HIGH ? "off." : "on."); } }
      
      







はい、ClassicUIを使用することを好みます(OpenHabのUIもプラグインです)。 2つの温度センサーのグラフを追加したい(1つのグラフでそれらを参照)。



まず、rrd4jのプラグインをインストールする必要があります。 幸いなことに、リポジトリにあります。







保存の構成は、ファイル/etc/openhab2/persistence/rrd4j.persistで行われます。 パスと名前から理解できるように、異なるバックエンドに異なるデータを保存することが可能です。 それらのそれぞれに対して、スケジュールとアイテムのリストを含むファイルがあります。



このファイルは、Quartz構文での保存間隔が設定されるストラテジーと、アイテムまたはグループにストラテジーが設定される要素という2つの設定グループで構成されています。



 Strategies { // Strategy name // | Seconds // | | Minutes // | | | Hours // | | | | Day of month // | | | | | Month // | | | | | | Day of week // | | | | | | | Year every5sec : "0/5 * * * * ?" every15sec : "0/15 * * * * ?" everyMinute : "0 * * * * ?" every30min : "0 30 * * * ?" everyHour : "0 0 * * * ?" everyDay : "0 0 0 * * ?" default = everyChange } Items { gTemperature* : strategy = everyMinute, restoreOnStartup }
      
      





以下の私の例では、gTemperatureは温度センサーの両方のアイテムを含むグループです(グループは名前の後にアスタリスクを付ける必要があります。そうしないと、メンバーではなくグループの値が保存されます)。



ファイルを保存すると、自動的に再読み込みされます。 ご覧のとおり、センサーの値は毎分保存されます。 これが最良のオプションです。 そしてなぜそう-私は以下に伝えます。



データはどこに保存されますか? フォルダー/ var / lib / openhab2 / persistence / rrd4j /。 各アイテムごとにファイルが作成され、ファイルサイズはすぐに、アーカイブを含むすべてのデータが保存されるようになります。 これは、RRDストレージの重要な機能として宣言されています-ファイルが制御不能に成長することはありません。



 root@chubarovo:/etc/openhab2# ll -h1 /var/lib/openhab2/persistence/rrd4j/ total 78K drwxr-xr-x 2 openhab openhab 4.0K Apr 7 21:53 ./ drwxr-xr-x 5 openhab openhab 4.0K Feb 18 18:59 ../ -rwxr-xr-x 1 openhab openhab 32 Dec 18 15:44 Readme.txt* -rw-r--r-- 1 openhab openhab 35K Apr 7 21:54 Test_temp1_soc.rrd -rw-r--r-- 1 openhab openhab 35K Apr 7 21:54 Test_temp2_soc.rrd
      
      





さて、すべてが問題ないので、サイトマップで自分自身にグラフィックを追加します。



 sitemap test label=" " { Text item=Test_button_soc label=" [MAP(ru.map):%s]" Text item=Test_temp1_soc Text item=Test_temp2_soc Chart item=gTemperature refresh=60000 period=4h }
      
      





画面上では次のように表示されます。







ところで、モバイルアプリケーションにはグラフィックもあります。







rrd4j(および元のRRDTools)のもう1つの興味深い機能は、組み込みのグラフレンダリングエンジンです。 OpenHabでは、このようなグラフを別のUI、HabPanelに挿入できます。 古い学校に見えます:







エンジンはリンクから直接利用できます。 次のようになります。



http://192.168.144.243:8080/rrdchart.png?groups=gTemperature&theme=black&period=h&h=464&w=447







wとhは、ピクセル単位のグラフのサイズです。 groupsパラメーターは、表示するグループの名前を設定します。 個々のアイテムには、itemsパラメーターを使用する必要があります。 複数のグループ/パラメーターを表示する必要がある場合は、コンマで区切って指定する必要があります。



さて、これはどのように機能しますか? 値はどれくらいの頻度で保存されますか? どれくらい保存されますか? とにかく、rrd4jには多くの設定がありますが、何もしませんでした!



現在のストレージを確認するには、OpenHabプラグインに付属のグラフィカルユーティリティを使用します。 テストサーバーにはXがないため、データファイルと.jarプラグインをメインのWindowsマシンにコピーしました。



もちろん、実行するにはJavaが必要です。 適切な.jarクラスを名前で実行するための便利な機能があります。 org.rrd4j.inspector.RrdInspectorが必要で、次のように実行します。



 java -cp rrd4j-2.1.1.jar org.rrd4j.inspector.RrdInspector
      
      





そして、これが私たちのアーカイブで見られるものです。







ここに、値を1分に1回以上保持する意味がない理由があります。 データは60秒ごとにストアに書き込まれ、より頻繁に保存しようとすると、すべての値の平均が記録されます。



センサーをもっと頻繁に読みたいので、rrd4jの構成を検討します。 はい、また、ボタンの状態を記録し、平均値(ボタンの使用状況は何ですか?)ではなく、ボタンの特定の期間にボタンが押されたかどうかを知るための期間の最大値を保存します。



すでに理解しているように、デフォルトの構成は私たちには適していません。 それで、それを変更するのは良いことです。 ストレージ設定は/etc/openhab2/services/rrd4j.cfgにあります。 これでファイルは空になりましたが、上部に構文のヒントがあります。



ですから、上記では一般的な言葉を既にフォーマットで書いています。 これで、構成を行う時間です。 この例からわかるように、設定は.defおよび.archivesの2行になります。 .itemsパラメーターは、構成が適用されるアイテムをリストします。 構成のないパラメーターはデフォルト設定で保存されます(上記のJava-lookerで確認しました)。



温度計の設定をしましょう:



 # each 15 sec temps.def=GAUGE,15,0,100,15 # 4h/15s : 1m/24h : 5m/7d temps.archives=AVERAGE,0.5,1,960:AVERAGE,0.5,4,1440:AVERAGE,0.5,20,2016 temps.items=Test_temp1_soc,Test_temp2_soc
      
      





ご覧のとおり、構文は従来のRRDToolsとは少し異なります。 .defでは、値のタイプをGAUGEに設定します-これは絶対値のストレージです。 さらに可能なハートビート、最小、および最大値。 そしてステップ。



ステップは、秒単位のカウント間の通常の間隔です。 15を選択しました。

ハートビートがステップに追加され、これが値を保存する最大時間間隔です。 この時間(私の場合、ステップ+ハートビート= 30秒)に値が記録されない場合、rrd4jはNaNをカウントに保存します。



.archivesでストレージ設定を設定します。 ファイルに書き込まれるものはすべてここで構成されます。 ご覧のとおり、いくつかのアーカイブが存在する可能性があります。 1つのアーカイブの構文は、ファイルの説明に記載されています。



集計関数として、AVERAGEを使用します。 私には温度があり、サンプルを組み合わせるときは平均を保つ必要があります。 次はxffパラメーターです。これはインターネットではあまり説明されていません。 ソースに入る必要がありました。 これは係数(実際にはパーセンテージ)であることが判明し、グループ化するときに結果のNaNが記録されるNaNの量を決定します。



たとえば、2つのアーカイブでは、係数が0.5の4つの値が結合され、2つ以上のソース値がNaNである場合、結果のNaNが記録されます。



以下のパラメーターは、1つのアーカイブに書き込まれるソース値の数と、保管する必要があるアーカイブ値の数(周期的に上書きされる)を指定します。



私のセットアップでは、次のパラメーターを使用して3つのアーカイブを作成しました。



•各値、合計960個(960 * 15秒= 4時間)を保存します。

•4つの値の平均、合計1440個(1440 * 15秒= 24時間)を保存します。

•20個の値の平均、合計2016個(2016 * 15秒= 7日)を保存します。



スキルを修正します。 ボタンの設定:



 # each 60 sec temps.def=DERIVE,60,0,100,60 # 6h/60s : 5m/24h : 5m/7d temps.archives=MAX,0.5,1,360:MAX,0.5,5,288:MAX,0.5,30,336 temps.items=Test_button_soc
      
      





ここでは、値を60秒ごとに保存し、最大値を保存します。



はい 永続化設定で永続化をrrd4j構成のステップよりも頻繁に設定すると、ストアは最初のアーカイブの集計関数で値をグループ化します。



それでは、OpenHabのセットアップに戻りましょう(Items部分のみを引用します)。



 Items { gTemperature* : strategy = every15sec, restoreOnStartup Test_button_soc : strategy = everyMinute, everyChange }
      
      





温度計の保存を15秒ごとに設定し、ボタンの設定を設定します。 それを毎分保存し、変更時に、集約関数MAXとともに、ボタンが1分間に少なくとも1回押された場合にアーカイブ1に書き込むことができるようにします。



私はサイトマップを完成させ、ここに私が見るものがあります:











OpenHabは、「スマートホーム」および住宅および共同サービスの自動化に適したソリューションです。 ロシアのコミュニティを利用して拡大しましょう!



All Articles