作ったもの
部屋の色んな情報を取得するシステムを作りました。リモートワークが中心であり、ずっと家にいあるので自分の部屋の環境改善をしたくなりました。IoT というほどではないかもしれないですが、ラズパイでのセンサを使った開発とかを経験してみたくなったので手を出したのですが、色々とやりたいことが増えた結果、色々なものが絡み合うシステムになってました。
機能
以下の情報を取得しています。
- 卓上 : obniz
- CO2 濃度
- 明るさ
- 室内 : RaspberryPi 4
- 温度
- 湿度
- 気圧
そして、以下の際に LINE Bot へと通知します。
- CO2 濃度が異常値を取得した時(他の値はまだ未対応です..)
- デバイスとの接続が切れた時(プログラムが停止してる時)
まだ寂しい感じですが、それぞれ以下のようなメッセージがプロアクティブに送られます。(上 : CO2 濃度が異常時、下 : プログラムの停止を確認した時)
システム構成
卓上の CO2 濃度、明るさを取得しています。
温湿度、気圧は正直室内どこでも良いかなって思ったのでテキトーに室内のおけるところに置いてます。
(CO2 濃度に関してはいい感じのサンプルで簡単に取得できたのがobniz だったので卓上で採っちゃいました。)
材料
ひとまずは一覧は以下の感じ
- RaspBerry Pi(4) : Python
- dht11
- BME180
- Obniz : node.js
- MH-Z19
- Groove_LightSensor
- Azure
- Azure IoT Hub
- Azure Functions
- Azure Bot Service
- App Service
RaspBerry Pi
恐らくは皆さんご存知かと思いますが、ラズパイです。僕はラズパイ4 を(昨年の夏に買って余らせてたので)使いました。
使用したセンサは温湿度センサの DHT11 と 気圧と温度を取得できる BME180 です。
この辺のセンサの選定理由は正直なところ、このスターターキット(リンクは Amazonより)に入ってたからです。DHT11 に関してはかなり参考情報がありましたが、正直気圧に関しては BMP280 等のセンサの方が情報多そうでした。そもそも、温度湿度気圧をまとめて取得できるセンサもそれなりにありそうですが、選定する時間やはんだごてがないことからこの組み合わせになりました。
Obniz
obniz は node.js 等を用いてセンサやモータをサクッと制御できるIoT デバイスです。
同じネットワーク(WiFi) 内にいる PC からプログラムを実行して動作させます。Python のプログラムを実行させているラズパイでこちらも実行させること等も可能です。
個人的に面白いと思う点は本当にサクッとセンサを試したりプログラムを作ったりできるところです。
パーツ ライブラリ があり、そこから公式に対応している(libraryのある) センサ等の確認と、なんとそのままブラウザから動作確認までできます。なので、それを少しいじると自分のプログラムに適用できたり、どんな値が取得できるかの確認もサクッとできます。
動作手順
Raspberry Pi で python(flask) アプリを実行します。以下みたいな感じです。(サーバのライブラリを色々使って見てたので、変なファイル名ですが見逃してください)
python flaskserver.py
次に、obniz の node.js プログラム実行
node .\storeData.js
node.js のプログラムからラズパイ側へのリクエストや Azure,GAS へのリクエストを送信してたりします。
このプログラム自体はラズパイからでも別の PC からでも同じ NW 上の PC であれば問題ありません。
個人的に、明るさは卓上のをとるのが一番普段の労働環境に近い情報が取れるかなという意味や、あまりラズパイに無理させるのは良くないかなって判断で別の PC にて実行してます。
簡単な作り方の解説
今回は卓上のセンサをある程度減らした上で、今後何かに使えそうな室内の情報は採れるだけ採ろうという感じで、かつ Azure の何らかの IoT 関連のサービスを使ってみたいため、デバイス周りをサクッと作りきってしまいたいことからこのような構成になりました。(買ったセンサが不具合っぽくて動かないことがいくつかあったのも影響していますが、、、)
なお、ラズパイ側と Obniz 側のプログラムは以下に雑な感じで置いてます。
https://github.com/MinoMinoMinoru/RoomManager
(別途コードの解説含めてどこかで記載するかもですが、現時点ではここにまとめると記事が長くなりそうなので割愛予定)
Raspberry Pi 側
Flask フレームワークで簡単な Web API サーバを実行しています。
Obniz 側から HTTP リクエスト(REST) を送信することでラズパイに接続したセンサの値を Obniz 側で取得してます。
使っているセンサとしては上述の通りであり、それらに関して Python を使ったlibraryがあるのでサクッとそれぞれの値を取得して、Flask に盛り込みました。dht11 に関してはライブラリが公開されてて楽に実行できました。BME180 は購入したスターターのサンプルをいじって実行しました。
Obniz 側
node.js をランタイムとして採用しました。こっちには CO2 濃度センサと明るさセンサで卓上の各情報を確認してます。
obniz にセンサを直差ししてる感じなので、割とコンパクトに収まってます。写真左のランプのようなが明るさセンサ、右下の金色の四角い箱がCO2センサです。
ここからラズパイにリクエストを投げて、ラズパイ側のセンサ情報を取得、その後それらの情報を基に以下を行っています。
- GAS へリクエストを投げて、スプレッドシートに情報を保存
- Azure IoT Hub を用いて死活管理
- 異常値の際には Azure Bot Service & App Service で LINE へ通知
ちなみに Obniz で MH_Z19 を使うサンプルプログラムは以下にあります。(あまりきれいではないかもですが)
https://github.com/MinoMinoMinoru/simple-obniz-mhz19
Azure 側
完全にソフト的な話になるのと、まじめに書くとそれなりの量になりそうなので、詳細については割愛して何となくの概要だけでも。
Azure IoT Hub
Azure IoT Hub はざっくりというと IoT デバイスの死活管理や制御をするサービスです。今回は obniz 側でセンサのデータを取得した際にデータを Azure IoT Hub に送信することでデータが届いていない = obniz のプログラムが停止している場合に通知を送るようにしてます。
なんか実際には Azure <-> デバイスの双方向通信とかもできるとかできないとかなので、その辺はまたの機会に検証してみたいところ。
あと、もしかしたらちゃんと使ったら「CO2 濃度が一定値を超えたら~~ 」等のロジックも Azure IoT Hub 側で出来たかもしれないです。(今回はデバイスが一個だけなので、デバイス側で判定しても良いかと思いますが、複数デバイスを管理するとなるとこういう機構で確認したら一元管理できるのかも?)
Azure Functions
Azure Functions はいわゆる Serverless Function です。AWS の lambda や GAS のようなものと思ってもらえたら。Azure のサービスを使用する際はカスタマイズが効きやすいので色んなサービス間の潤滑油のように使用することもあります。今回も似たような感じで、IoT Hub でデバイスが動いてないのを確認した際に Bot との連携をする用途で使ってます。
Azure Bot Service & App Service
Azure Bot Service は Bot を作成する際に使用するサービスです。例えば Taems や LINE, slack 等との接続を簡単にできます。よくある Serverless function 等と違う点としては認証の処理等を Bot Service に任せることで、シークレットの扱い等をコードと分離して実装に集中できること等があります。
そして、しばしば App Service に Bot アプリをホストして使用します。App Service は Web アプリをホストするサービスのようなイメージで、例えば Function と異なりいくつもエンドポイントを用意することや、インメモリで何等かのデータを一時的に保存してステートを一時的に維持したやり取り等もできます。
Azure Bot Service を使用する際にはよく Bot Framework SDK を用いて作成した Bot アプリを App Service にホストして使用します。
今回は CO2 が異常値を検知した際に通知するエンドポイントと、デバイスとの接続が切れた際に通知するエンドポイントを用意した感じです。
Google App Script
Google App Script は現時点で無料で使用できる Serverless Function のようなもので、SpreadSheet 等の Google App との連携が抜群なサービスです。個人的にはちょっとしたデータの保存等に関してはかなり使いやすい印象です。
具体的なやり方の解説などは割愛しますが、コート量としても以下くらいの簡単な機能だけ実装しました。
本当に POST で送られてきた値をシートに保存するくらいです。
const sheetname = "<sheet の Name>"
function doPost(e){
// var params = JSON.parse(e);
const getData = JSON.parse(e.postData.getDataAsString());
var sensorData = [];
sensorData[0]=Utilities.formatDate(new Date(), "JST", "MM/dd HH:mm:ss");
sensorData.push(getData.temp)
sensorData.push(getData.humid)
sensorData.push(getData.co2)
sensorData.push(getData.pressure)
sensorData.push(getData.light)
appendRow2Sheet(sensorData,sheetname)
return ContentService.createTextOutput(JSON.stringify({'content': 'post ok',
'co2':getData.co2,'row':getData})).setMimeType(ContentService.MimeType.JSON);
}
function appendRow2Sheet(data,sheetname) {
const spreadsheet = SpreadsheetApp.openById('<sheet の ID>');
var sheet = spreadsheet.getSheetByName(sheetname);
sheet.appendRow(data);
}
詰まった点
センサーの個体差
実は Obniz に対応してるセンサで温度湿度を取得できるものとかもあったのですが、買ってみたところ安いやつだからか、ピンが緩くて使えなかったみたいなことがありました。
CO2 の取得
CO2 センサ mh_z19 はobniz で正式にサポートされたセンサではないので、uart で無理やり値取得することになります。幸い、たまたま見つけた個人ブログのやり方を真似したら取得できたので何とかなりましたがそこそこ詰まりました。(ラズパイ側でも試したりしてましたが、ちょこちょこ詰まりました)
改善点
安定性
ラズパイ側での DHT11 の値がちょこちょこエラーになって取得できてないということがあります。リクエストを Flask が受けてセンサで値を取得するまでの間でなんかタイミングの良しあしがあるのかも?あと、現在はかなり改善しましたが、Obniz のプログラム側が不安定で気づいたらクラッシュしてるってこともありました。(ラズパイで実行とか別端末で実行とか色々と影響範囲はありそう)
復旧方法
ラズパイで実行してる Flask アプリが落ちた時に復旧させる方法を考えないとなと。
今は基本的に VSCode で Remote-SSH という拡張機能を用いて、普段使いの PC から Remote 接続して Flask アプリを実行させてます。
そして、Fask アプリが落ちた時に接続が切れていること等があり、再度接続してアプリを実行しなおすといったことをするのですが、それがちょっと手間かつそもそもアプリが落ちてるのかの確認がうまくできずラズパイ再起動させたりしてます。ここをうまくやりたいところ。
取得したデータの活用
せっかく取得したデータ、なんかの役に立てないなと思ってます。機会学習系とかと組み合わせて何か使い道がないかなと模索中。
Proactive Message のバリエーション
現状はとりあえず完成させるということで CO2 濃度に絞って LINE で通知させました。なので、もっと他のセンシングデータとかも使て行きたいところ。
-
Minoru
さんが
2021/02/23
に
編集
をしました。
(メッセージ: 初版)
ログインしてコメントを投稿する