自宅の環境センサーを「EnOcean STM 550B」に入れ替えた話


はじめに

先日(2020/8/5)に行われた『「実践Node-RED活用マニュアル」書籍出版記念イベントのYoutube Live』で中畑さんから紹介のあった環境センサー「EnOcean STM 550B」が電池不要との事だったので、『Elastic Stackで室内環境センサーのデータを管理』で利用していた同じくBLEビーコンのLinkingデバイスの代わりになるのではないかと早速試してみました。

環境

  • 収集機器
    • Raspberry Pi 4B (RAM:4GB)
  • 環境センサー

    • EnOcean STM 550B

      Youtube Live後に発注したら、翌日届きました
  • ソフトウェア

    • Raspbian (Buster)
    • Node-RED v1.0.3 + node-red-contrib-blebeacon-scanner v1.0.1
    • Elasticsearch 7.8.0 (自宅のラズパイ4B*4台のkubernetesクラスタにデプロイ)
      接続先は「localhost:30920」です。

情報収集

使い方やデータ構造は、以下の情報を参照しました。

フロー作成

個人的な縛りプレイなのですが「functionノードを極力使わない」ようにしています。
バイナリバッファからデータを取り出して計算するので、functionノードを使いたくなるのですが、おなじみのchangeノードのJSONataで頑張ってみました。

changeノード内は若干カオスです。
言い訳をすると、JSONataでバイナリバッファを参照する方法を見つけられなかったので、代入で一旦変数に入れてJSONataで計算させています。

フローを書き出したJSONは以下です。(Elasticsearchのサブフローも含んでます)
※8/16修正。Changeノードでmsg.deviceが「msg」.payload.idとなってなかった。

json
[{"id":"3f7774f5.a6a20c","type":"subflow","name":"Elasticsearch","info":"","category":"","in":[{"x":50,"y":30,"wires":[{"id":"c5bb15c.4c10de8"}]}],"out":[{"x":580,"y":30,"wires":[{"id":"19d2a3b.d048a5c","port":0}]}],"env":[],"color":"#E6E0F8","icon":"font-awesome/fa-database"},{"id":"eeda88c1.f8b278","type":"http request","z":"3f7774f5.a6a20c","name":"Elasticsearch","method":"use","ret":"txt","paytoqs":false,"url":"","tls":"","persist":false,"proxy":"","authType":"basic","x":340,"y":30,"wires":[["19d2a3b.d048a5c"]]},{"id":"c5bb15c.4c10de8","type":"change","z":"3f7774f5.a6a20c","name":"msg.headers","rules":[{"t":"delete","p":"headers","pt":"msg"},{"t":"set","p":"headers","pt":"msg","to":"{\"Content-Type\":\"application/json\",\"Connection\":\"close\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":170,"y":30,"wires":[["eeda88c1.f8b278"]]},{"id":"19d2a3b.d048a5c","type":"json","z":"3f7774f5.a6a20c","name":"","property":"payload","action":"","pretty":false,"x":490,"y":30,"wires":[[]]},{"id":"bc591a17.cb1a98","type":"switch","z":"d912a1ba.79637","name":"","property":"payload.id","propertyType":"msg","rules":[{"t":"eq","v":"e50010000ef1","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":300,"y":100,"wires":[["c556476d.e42bb8"]]},{"id":"c556476d.e42bb8","type":"delay","z":"d912a1ba.79637","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":450,"y":100,"wires":[["c0d9cc8d.c70d1","b5ad04fe.e15eb8","c406ebdd.d15478"]]},{"id":"c0d9cc8d.c70d1","type":"change","z":"d912a1ba.79637","name":"湿度抽出","rules":[{"t":"set","p":"bin","pt":"msg","to":"payload.other.10","tot":"msg"},{"t":"set","p":"data","pt":"msg","to":"$number(bin * 0.5)","tot":"jsonata"},{"t":"set","p":"service","pt":"msg","to":"humidity","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":50,"wires":[["47a25439.dabd2c"]]},{"id":"b5ad04fe.e15eb8","type":"change","z":"d912a1ba.79637","name":"温度抽出","rules":[{"t":"set","p":"bin","pt":"msg","to":"payload.other.8","tot":"msg"},{"t":"set","p":"data","pt":"msg","to":"$number(bin * 256)","tot":"jsonata"},{"t":"set","p":"bin","pt":"msg","to":"payload.other.7","tot":"msg"},{"t":"set","p":"data","pt":"msg","to":"$number((data + bin) * 0.01)","tot":"jsonata"},{"t":"set","p":"service","pt":"msg","to":"temperature","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":100,"wires":[["47a25439.dabd2c"]]},{"id":"c406ebdd.d15478","type":"change","z":"d912a1ba.79637","name":"照度抽出","rules":[{"t":"set","p":"bin","pt":"msg","to":"payload.other.13","tot":"msg"},{"t":"set","p":"data","pt":"msg","to":"$number(bin * 256)","tot":"jsonata"},{"t":"set","p":"bin","pt":"msg","to":"payload.other.12","tot":"msg"},{"t":"set","p":"data","pt":"msg","to":"$number(data + bin)","tot":"jsonata"},{"t":"set","p":"service","pt":"msg","to":"illuminance","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":150,"wires":[["47a25439.dabd2c"]]},{"id":"f474c06e.e0876","type":"BLE Beacon Scanner","z":"d912a1ba.79637","name":"","x":120,"y":100,"wires":[["bc591a17.cb1a98"]]},{"id":"b71a30db.2f93c","type":"subflow:3f7774f5.a6a20c","z":"d912a1ba.79637","x":1250,"y":100,"wires":[[]]},{"id":"8d95598c.498b78","type":"template","z":"d912a1ba.79637","name":"ES Query JSON","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\n    \"date\": \"{{{date}}}\",\n    \"device\": \"{{{device}}}\",\n    \"{{{service}}}\": {{{data}}}\n}","output":"str","x":1070,"y":100,"wires":[["b71a30db.2f93c"]]},{"id":"47a25439.dabd2c","type":"change","z":"d912a1ba.79637","name":"method POST _doc","rules":[{"t":"set","p":"device","pt":"msg","to":"payload.id","tot":"msg"},{"t":"set","p":"date","pt":"msg","to":"$now()\t","tot":"jsonata"},{"t":"set","p":"method","pt":"msg","to":"POST","tot":"str"},{"t":"set","p":"url","pt":"msg","to":"http://localhost:30920/sensor-","tot":"str"},{"t":"change","p":"url","pt":"msg","from":"$","fromt":"re","to":"service","tot":"msg"},{"t":"change","p":"url","pt":"msg","from":"$","fromt":"re","to":"/_doc","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":100,"wires":[["8d95598c.498b78"]]}]

小数点計算の誤差については、そこまで精度は求めていないのでそのままにして利用時に丸めたりしています。(Kibana側のマッピングとか)
KibanaのDiscoverでElasticsearchのデータを参照すると、以下のようになりました。

おわりに

以前、Linkingデバイスで構築していたデータ取得部分を変えただけなので、すんなり入れ替える事ができました。
Linkingデバイス利用時との比較ですが、大幅にビーコン強度が上がったので大満足です。私の自宅環境特有かもしれませんが、Linkingデバイスは30cmも離せない強度だったのですが、EnOcean STM 550Bは1m以上離してもビーコンが届きます。

少し悩んでいる事は、太陽電池を生かすには照度の高い場所を選びたいけど、そうなると温度の測定値が高くなってしまうんですよね。
自宅リビングの中途半端な照度+電池でどれくらい稼働するかは見てみたいと思います。

簡単な記事ですが最後に、スマートライト株式会社の中畑さんに良いデバイスを紹介して頂いた事と、購入時に色々フォローしていただいた事に感謝の意をお伝えします。ありがとうございました!