RETENTION POLICYラズパイとESP32とシリアル通信でラズパイから制御します。
ESP32はWifi通信すると使えなくなるPINが出てくるので・・ラズパイのUSBにESP32を接続してシリアル通信で直接水位データを取得していきます。
BLEで取得
ESP32のBluetooth MACアドレスを調べる
$ sudo hcitool lescan LE Scan ... EF:FC:25:C5:D2:4A (unknown) 38:34:DB:5D:05:6D (unknown) 38:63:4B:18:FE:64 (unknown) 84:0D:8E:06:65:8E (unknown) 84:0D:8E:06:65:8E Long name works now 03:4B:A5:0B:C5:9D (unknown) 4C:65:A8:D0:8E:1C (unknown)
84:0D:8E:06:65:8EがESP32のMACアドレス。
接続してみる
$ gatttool -b 84:0D:8E:06:65:8E -I [84:0D:8E:06:65:8E][LE]> connect Attempting to connect to 84:0D:8E:06:65:8E Connection successful [84:0D:8E:06:65:8E][LE]> (gatttool:32098): GLib-WARNING **: Invalid file descriptor.#これが出たら再度connectする。 [84:0D:8E:06:65:8E][LE]> characteristics handle: 0x0002, char properties: 0x20, char value handle: 0x0003, uuid: 00002a05-0000-1000-8000-00805f9b34fb handle: 0x0015, char properties: 0x02, char value handle: 0x0016, uuid: 00002a00-0000-1000-8000-00805f9b34fb handle: 0x0017, char properties: 0x02, char value handle: 0x0018, uuid: 00002a01-0000-1000-8000-00805f9b34fb handle: 0x0019, char properties: 0x02, char value handle: 0x001a, uuid: 00002aa6-0000-1000-8000-00805f9b34fb handle: 0x0029, char properties: 0x3a, char value handle: 0x002a, uuid: beb5483e-36e1-4688-b7f5-ea07361b26a8 [84:0D:8E:06:65:8E][LE]> char-read-hnd 0x002a Characteristic value/descriptor: 3c 11 00 00
$ sudo apt-get install bluez-hcidump
配線
- + : 3.3V
- – : GND
- S : GPIO36
水位センサー 簡単なスケッチ
void setup() { Serial.begin(115200); } void loop() { int sensorValue; sensorValue = analogRead(36); Serial.print("sensor = "); Serial.println(sensorValue); delay(3000); }
水位が変わってきたら1秒毎にInfluxDBに送る。
水位が変わらない場合は3分おき程度で送る。
だいたい1200弱くらいから水が入っているのを感知していて2300くらいで満タン近くになるのでアラートになったほうがよさそう
InfluxDBのデータを間引く
1秒おきに水位データをInfluxDBにアップしているので、そのうちラズパイのMicroSDカードが満タンになって動かなくなりそうなので、30分おきの水位データを保存してから1秒おきの水位データは一日で破棄してみる。
なので過去の不要なデータを間引きする。
RETENTION POLICY(RP)を作成する
InfluxDBのデータをどのくらい保存しておくかのRETENTION POLICYを作成していきましょう。
デフォルトのRETENTION POLICYはautogenで保存期間が無制限になっているのでデータがディスク容量を消費していきますので一定期間ごとにデータを削除するためにRetention Policyを設定します。
ChronographでRETENTION POLICYを作成
Chronographをラズパイにインストールしている場合はWebページからRETENTION POLICYを作成しましょう。もしまだChronographをインストールしていない方はラズパイのシェルで以下のようにすればインストールできます。
$ sudo apt-get install chronograf
Chronographのアドレスは「http://localhost:8888/か、SSHで他のPCからアクセスする場合は「http://192.168.xx.xx:8888/」と、IPアドレスを指定してアクセスします。
左メニューの王冠アイコン > Databasesをクリックして、RETENTION POLICYを追加するデータベースの「+ Add Retention Policy」をクリックする。
以下のように設定してみました。
- Retention Policy:1day(ポリシー名)
- Duration:24h(有効期間、無制限はINF)
- Replication Factor:1(クラスターの複製数)
influxコマンドでリテンションポリシーを作成
リテンションポリシー(RETENTION POLICY)は以下のようにinfluxコマンドからDBがに入っても作成できます。
$ influx > CREATE RETENTION POLICY "2day" ON "sensor" DURATION 2d REPLICATION 1
上記の3箇所を変更してお好みのポリシーを作れます。
- ポリシー名:2day
- データベース:sensor
- 有効期間:2d(2日間)
1日でデータを削除と、2日で削除するリテンションポリシーを作って以下のようになりました。
リテンションポリシーの適用
リテンションポリシーはデータを登録するときにしか設定できないようです。特に指定しない時はDefalutのAutogen(無制限)のRetention Policyを使用するのでデータは削除されることはありません。
上の作成したリテンションポリシーを使って1日や2日で削除したい場合は以下のようにデータを入れるときに設定するか、次にあげるContinuous Queryを使用してデータを間引くこともできます。
作成したリテンションポリシーはInfluxDBにデータをインサートするときに使う。以下のように「retentionPolicy=2day」を追加する。
$ influx > use sensor > INSERT table1,place=room,host=espd32,retentionPolicy=2day,type=12 temp=17.025213452336,humi=56.0211211356
こうすることで、インサートしたデータの有効期限が2日になって2日後に削除される。
Continuous Query 作成
続いてContinuous Queryを作成していきます。こちらは1秒置きの水位データを間引いて30分置きにして保存します。
CREATE CONTINUOUS QUERY "CONTINUOUSクエリー名" ON "デーベース" BEGIN SELECT * INTO "リテンションポリシー名"."新しいMEASUREMENT名" FROM "既存のMEASUREMENT名" GROUP BY time(30m) END
$influx > use sensor > CREATE CONTINUOUS QUERY "cq30m" ON "sensor" BEGIN SELECT mean("wlevel") AS "wlevel" INTO "autogen"."water_level_past" FROM "water" GROUP BY time(30m) END
11/17 サブのラズパイ3B+2で以下のようなエラーになる?
$ vim syslog Nov 17 06:25:42 Raspi3B2 influxd[435]: ts=2019-11-16T21:25:42.254134Z lvl=info msg="Error executing query" log_id=0J8Ws~aW000 service=continuous_querier query="CREATE CONTINUOUS QUERY cq30m ON sensor BEGIN SELECT * INTO sensor.autogen.water_level_past FROM sensor.autogen.water GROUP BY time(30m) END" error="continuous queries must be aggregate queries" Nov 17 06:25:42 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:42 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:42 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:42 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:42 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:42 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:42 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:43 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:43 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:43 Raspi3B2 python[342]: display_power=0 Nov 17 06:25:43 Raspi3B2 influxd[435]: ts=2019-11-16T21:25:43.256145Z lvl=info msg="Error executing query" log_id=0J8Ws~aW000 service=continuous_querier query="CREATE CONTINUOUS QUERY cq30m ON sensor BEGIN SELECT * INTO sensor.autogen.water_level_past FROM sensor.autogen.water GROUP BY time(30m) END" error="continuous queries must be aggregate queries"
最終的な設定
sensor.waterに登録時に以下のようにretentionPolicyを指定してインサートする。
INSERT water,host=esp32-wlevel,retentionPolicy=1day,place=leaf-wl32 wlevel=1232
おなじMEASUREMENTに間引きしたデータをautogenリテンションポリシーで書き込んで古いデータを間引きした状態で使う。
1秒おきに保存するとInfluxDBが重くなってCPUを食い尽くすみたい。
なので、2時間でデータを削除するようにした。
INSERT water,host=esp32-wlevel,retentionPolicy=2hours,place=leaf-wl32 wlevel=1232
Grafanaで2秒間隔でリアルタイム表示
自動でポンプをオン・オフするようにしましたが、エラーが出ると水漏れしちゃうので、しばらくは手動で監視しておくためにGrafanaでリアルタイム表示させてみました。
本当は1秒間隔がよかったのですが、1秒おきに「N/A」表示になるので2秒間隔にしました。
Grafana6.2からはBar Guageが追加された
水位を表示させるにはピッタリなBar Guage↓が追加されたので早速アップグレードしてみた。この表示だと培養容器に水がどのくらいあるのかひと目で分かる。ただしアラートに機能が無い。
こちら↓にサンプル表示がありますので気になる方はチェックしてみてください。
すでにGrafanaをインストールしてあっても以下の操作をすれば上書きされました。
$ wget https://dl.grafana.com/oss/release/grafana-rpi_6.2.5_armhf.deb $ sudo dpkg -i grafana-rpi_6.2.5_armhf.deb $ rm grafana-rpi_6.2.5_armhf.deb
アップグレードしたらブラウザをリロードして左下の「?」アイコンをマウスオーバーしたらGraganaのバージョンが確認できる。
ESP32 水位計測してInfluxDBに送るスケッチ 6水槽分
/*
ラズパイにUSBで接続してWIFI通信する。
int myPins[] = {2, 4, 12, 14, 15, 26, 27,13,25};//BT,Wifiを使うとこのPINは使えない
23,22,1,3,21,19,18,5,17,16も使えない?Wifi+水位センサーでは無理っぽい。
36,39,34,35,32,33
*/
#include <Wire.h>
#include <HTTPClient.h>
//Wi-Fi情報
#define WIFI_SSID "WIFIのSSISID"
#define WIFI_PASSWORD "WIFIのパスワード"
//InfluxDB
#define MEASUREMENT "water"
#define HOST "esp32-wlevel"
//rp=1hour 1時間でデータを削除するRetention Policyを作っておく
const char* influxUrl = "http://192.168.31.53:8086/write?db=sensor&rp=1hour";
const char* influxUser = "root";
const char* influxPassword = "gonet1600";
//水位を計測
//InfluxDB送信 ラズパイに接続
void postToInfluxDB() {
int myPins[] = {36,39,34,35,32,33};//結局この6つのピンしか使えない!!
int awlevel;
Serial.println("+++++++++++++++++++++++++++++++++++");
for(int i=0; i<6; i++){
awlevel = analogRead(myPins[i]);
Serial.print( myPins[i] );
Serial.print("---");
Serial.println(awlevel);
String influxData = MEASUREMENT ",host=" HOST;
influxData += ",place=leaf-wl";
influxData += myPins[i];
influxData += " wlevel=";
influxData += awlevel;
HTTPClient http;
http.begin(influxUrl);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
http.setAuthorization(influxUser, influxPassword);
int httpCode = http.POST(influxData);
http.end();
if (httpCode == HTTP_CODE_OK) {
Serial.print( influxData + "-------NO \n");
} else {
Serial.print( influxData + "-------OK! \n");
}
delay(100);
}
}
void setup() {
Serial.begin(115200);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("connecting");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("connected: ");
Serial.println(WiFi.localIP());
}
void loop() {
postToInfluxDB();
delay(1000);//1秒おきに送信
}
コメント